, pcem)
AC_CANONICAL_HOST
@@ -27,12 +27,12 @@ AC_MSG_CHECKING([whether to enable debugging])
AC_ARG_ENABLE(debug,
AC_HELP_STRING([--enable-debug], [build debug executable]))
if test "$enable_debug" = "yes"; then
- CFLAGS="-Wall -O0 -g -D_DEBUG"
- CXXFLAGS="-Wall -O0 -g -D_DEBUG"
+ CFLAGS="$CFLAGS -Wall -O0 -g -D_DEBUG -fcommon"
+ CXXFLAGS="$CXXFLAGS -Wall -O0 -g -D_DEBUG -fcommon"
AC_MSG_RESULT([yes])
else
- CFLAGS="-O3"
- CXXFLAGS="-O3"
+ CFLAGS="$CFLAGS -O3 -fcommon"
+ CXXFLAGS="$CXXFLAGS -O3 -fcommon"
AC_MSG_RESULT([no])
fi
@@ -140,6 +140,7 @@ case "$host" in
LIBS="$LIBS -framework OpenGL"
LIBS="$LIBS -framework OpenAL"
build_macosx="yes"
+ CFLAGS="$CFLAGS -DHAVE_UNISTD_H"
;;
*-*-cygwin* | *-*-mingw32*)
AC_CHECK_LIB([opengl32], [main], [], \
@@ -159,6 +160,20 @@ case "$host" in
[echo "You need to install the OpenAL library."
exit -1])
build_linux="yes"
+ CFLAGS="$CFLAGS -DHAVE_UNISTD_H"
+ ;;
+ *-*-freebsd*)
+ CFLAGS="$CFLAGS -I/usr/local/include"
+ CXXFLAGS="$CXXFLAGS -I/usr/local/include"
+ LDFLAGS="$LDFLAGS -L/usr/local/lib"
+ AC_CHECK_LIB([GL], [glGetError], [], \
+ [echo "You need to install the OpenGL library."
+ exit -1])
+ AC_CHECK_LIB([openal], [alGetError], [], \
+ [echo "You need to install the OpenAL library."
+ exit -1])
+ build_other="yes"
+ CFLAGS="$CFLAGS -DHAVE_UNISTD_H"
;;
*)
AC_CHECK_LIB([GL], [glGetError], [], \
@@ -171,6 +186,7 @@ case "$host" in
;;
esac
+CFLAGS="$CFLAGS $SDL_CFLAGS"
LIBS="$LIBS $WX_LIBS $SDL_LIBS"
AM_CONDITIONAL(OS_LINUX, [test "$build_linux" = "yes"])
diff --git a/install-sh b/install-sh
old mode 100644
new mode 100755
diff --git a/readme.html b/readme.html
new file mode 100644
index 0000000..8694110
--- /dev/null
+++ b/readme.html
@@ -0,0 +1,1467 @@
+
+
+
+
+
+
+ readme
+
+
+
+
+
+
+Latest version: v17 Changelog
+PCem is licensed under GPL v2.0, see COPYING for more details.
+You can submit patches on our forum . Before you do, please note the guidelines for submitting patches.
+❗ Note: NO COPYRIGHTED ROM FILES ARE INCLUDED NOR WILL THEY BE. PLEASE DO NOT ASK FOR THEM.
+BSD and Linux supplement (v17)
+You will need the following libraries (and their dependencies):
+
+SDL2
+wxWidgets 3.x
+OpenAL
+
+Open a terminal window, navigate to the PCem directory then enter:
+Linux
+./configure --enable-release
+make
+BSD
+./configure --enable-release-build
+gmake
+then ./pcem to run.
+The Linux/BSD versions store BIOS ROM images, configuration files, and other data in ~/.pcem
+configure options are :
+ --enable-release-build : Generate release build. Recommended for regular use.
+ --enable-debug : Compile with debugging enabled.
+ --enable-networking : Build with networking support.
+ --enable-alsa : Build with support for MIDI output through ALSA. Requires libasound.
+The menu is a pop-up menu in the Linux/BSD port. Right-click on the main window when mouse is not captured.
+CD-ROM support currently only accesses /dev/cdrom. It has not been heavily tested.
+Links
+PCem emulates the following hardware (as of v17):
+
+
+
+
+
+Systems
+8088 based
+
+
+
+
+
+
+1981
+IBM PC 8088 at 4.77 MHz 16KB - 640KB RAM (min. 64KB)
+ibmpc/pc102782.bin ibmpc/basicc11.f6 ibmpc/basicc11.f8 ibmpc/basicc11.fa ibmpc/basicc11.fc
+
+
+1983
+Compaq Portable Plus 8088 at 4.77 MHz 128KB - 640KB RAM
+compaq_pip/Compaq Portable Plus 100666-001 Rev C.bin
+
+
+1983
+IBM XT 8088 at 4.77 MHz 64KB - 640KB RAM
+ibmxt/5000027.u19 ibmxt/1501512.u18
+
+
+1983
+Leading Edge Model M 8088 at 7.16 MHz 128KB - 704KB RAM
+leadingedge_modelm/Leading Edge - Model M - BIOS ROM - Version 4.71.bin
+
+
+1984
+IBM PCjr [5] 8088 at 4.77 MHz 64KB - 640KB RAM (min. 128KB) Built-in 16 colour graphics 3 voice sound Not generally PC compatible.
+ibmpcjr/bios.rom
+
+
+1984
+Tandy 1000 [5] 8088 at 4.77 MHz 128KB - 640KB RAM Built-in 16 colour graphics 3 voice sound
+tandy/tandy1t1.020
+
+
+1985
+NCR PC4i 8088 at 4.77 MHz 256KB - 640KB RAM
+ncr_pc4i/NCR_PC4i_BIOSROM_1985.BIN
+
+
+1986
+DTK Clone XT 8088 at 8/10 MHz 64KB - 640KB RAM
+dtk/dtk_erso_2.42_2764.bin
+
+
+1986
+Phoenix XT clone 8088 at 8/10 MHz 64KB - 640KB RAM
+pxxt/000p001.bin
+
+
+1987
+Tandy 1000HX 8088 at 7.16 MHz 256KB - 640KB RAM Built-in 16 colour graphics 3 voice sound Has DOS 2.11 in ROM
+tandy1000hx/v020000.u12
+
+
+1987
+Thomson TO16 PC 8088 at 9.54 MHz 512KB - 640KB RAM
+to16_pc/TO16_103.bin
+
+
+1987
+Toshiba T1000 [1] [5] 8088 at 4.77 MHz 512KB - 1024KB RAM CGA on built-in LCD
+t1000/t1000.rom t1000/t1000font.rom
+
+
+1987
+VTech Laser Turbo XT 8088 at 10 MHz 640KB RAM
+ltxt/27c64.bin
+
+
+1987
+Zenith Data SupersPort 8088 at 8 MHz 128KB - 640KB RAM Built-in LCD video is not currently emulated
+zdsupers/z184m v3.1d.10d
+
+
+1988?
+©Anonymous Generic Turbo XT BIOS 8088 at 8+ MHz 64KB - 640KB RAM
+genxt/pcxt.rom
+
+
+1988
+Atari PC3 8088 at 8 MHz 640KB RAM
+ataripc3/AWARD_ATARI_PC_BIOS_3.08.BIN
+
+
+1988
+Juko XT clone
+jukopc/000o001.bin
+
+
+1988
+Schneider Euro PC 8088 at 9.54 MHz 512KB - 640KB RAM
+europc/50145 europc/50146
+
+
+1989
+AMI XT clone 8088 at 8+ MHz 64KB - 640KB RAM
+amixt/ami_8088_bios_31jan89.bin
+
+
+2015
+Xi8088 8088 at 4.77-13.33 MHz 640KB RAM
+xi8088/bios-xi8088.bin
+
+
+
+8086 based
+
+
+
+
+
+
+1984
+Compaq Deskpro 8086 at 8 MHz 128KB - 640KB RAM
+deskpro/Compaq - BIOS - Revision J - 106265-002.bin
+
+
+1984
+Olivetti M24 [5] 8086 at 8 MHz 128KB - 640KB RAM Built-in enhanced CGA (supports 640x400x2)
+olivetti_m24/olivetti_m24_version_1.43_low.bin olivetti_m24/olivetti_m24_version_1.43_high.bin
+
+
+1986
+Amstrad PC1512 [5] 8086 at 8 MHz 512KB - 640KB RAM Enhanced CGA (supports 640x200x16) Custom mouse port
+pc1512/40043.v1 pc1512/40044.v2 pc1512/40078.ic127
+
+
+1987
+Amstrad PC1640 [5] 8086 at 8 MHz 640KB RAM Built-in Paradise EGA Custom mouse port
+pc1640/40043.v3 pc1640/40044.v3 pc1640/40100
+
+
+1987
+Toshiba T1200 [1] [5] 8086 at 9.54 MHz 1MB - 2MB RAM CGA on built-in LCD
+t1200/t1200_019e.ic15.bin t1200/t1000font.rom
+
+
+1988
+Amstrad PPC512/640 [5] 8086 at 8 MHz 512KB - 640KB RAM Built-in CGA w/ plasma display
+ppc512/40107.v2 ppc512/40108.v2 ppc512/40109.bin
+
+
+1988
+Sinclair PC200/Amstrad PC20 [5] 8086 at 8 MHz 512KB - 640KB RAM Built-in CGA (supports TV-out 50hz PAL)
+pc200/pc20v2.0 pc200/pc20v2.1 pc200/40109.bin
+
+
+1988
+VTech Laser XT3 8086 at 10 MHz 512KB - 1152KB RAM
+lxt3/27c64d.bin
+
+
+1989
+Amstrad PC2086 [5] 8086 at 8 MHz 640KB RAM Built-in VGA
+pc2086/40179.ic129 pc2086/40180.ic132 pc2086/40186.ic171
+
+
+1989
+Tandy 1000SL/2 [5] 8086 at 9.54 MHz 512KB - 768KB RAM Built-in 16 colour graphics 4 voice sound
+tandy1000sl2/8079047.hu1 tandy1000sl2/8079048.hu2
+
+
+1990
+Amstrad PC3086 [5] 8086 at 8 MHz 640KB RAM Built-in VGA
+pc3086/fc00.bin pc3086/c000.bin
+
+
+1991
+Amstrad PC5086 8086 at 8 MHz 640KB RAM
+pc5086/sys_rom.bin
+
+
+
+286 based
+
+
+
+
+
+
+1984
+IBM AT 286 at 6 or 8 MHz 256KB - 16MB RAM
+ibmat/at111585.0 ibmat/at111585.1
+
+
+1986
+Compaq Portable II 286 at 8 MHz 256KB - 15MB RAM
+compaq_pii/109739-001.rom compaq_pii/109740-001.rom
+
+
+1986
+IBM XT Model 286 286 at 6 MHz 256KB - 16MB RAM
+ibmxt286/BIOS_5162_21APR86_U34_78X7460_27256.BIN ibmxt286/BIOS_5162_21APR86_U35_78X7461_27256.BIN
+
+
+1986
+Toshiba T3100e [1] [5] 286 at 12 MHz 1MB - 5MB RAM CGA on gas-plasma display
+t3100e/t3100e_font.bin t3100e/t3100e.rom
+
+
+1987
+IBM PS/2 Model 50 [5] 286 at 10 MHz 1MB - 16MB RAM Built-in VGA MCA bus
+i8550021/90x7420.zm13 i8550021/90x7423.zm14 i8550021/90x7426.zm16 i8550021/90x7429.zm18
+
+
+1988
+Bull Micral 45 286 at 12 MHz 1MB - 6MB RAM
+bull_micral_45/even.fil bull_micral_45/odd.fil
+
+
+1988
+Commodore PC30-III 286 at 12 MHz 512KB - 16MB RAM
+cmdpc30/commodore pc 30 iii even.bin cmdpc30/commodore pc 30 iii odd.bin
+
+
+1988
+IBM PS/2 Model 30-286 286 at 10 MHz 1MB - 16MB RAM Built-in VGA MCA bus
+ibmps2_m30_286/33f5381a.bin
+
+
+1989
+Epson PC AX 286 256KB - 16MB RAM
+epson_pcax/EVAX epson_pcax/ODAX
+
+
+1989
+Epson PC AX2e 286 at 12 MHz 256KB - 16MB RAM
+epson_pcax2e/EVAX epson_pcax2e/ODAX
+
+
+1990
+AMI 286 clone 286 at 8+ MHz 512KB - 16MB RAM
+ami286/amic206.bin
+
+
+1990
+Award 286 clone 286 at 8+ MHz 512KB - 16MB RAM
+award286/award.bin
+
+
+1990
+Dell System 200 286 at 12 MHz 640KB - 16MB RAM
+dells200/dell0.bin dells200/dell1.bin
+
+
+1990
+IBM PS/1 Model 2011 [5] 286 at 10 MHz 512KB - 16MB RAM Built-in VGA DOS 4.01 + GUI menu system in ROM
+ibmps1/f80000.bin
+
+
+?
+Goldstar GDC-212M 286 at 12 MHz 512KB - 4MB RAM
+gdc212m/gdc212m_72h.bin
+
+
+?
+GW-286CT GEAR 286 at 8+ MHz 512KB - 16MB RAM
+gw286ct/2ctc001.bin
+
+
+?
+Hyundai Super-286TR 286 at 12 MHz 1MB - 4MB RAM
+super286tr/award.bin
+
+
+?
+Samsung SPC-4200P 286 at 12 MHz 512KB - 2MB RAM
+spc4200p/u8.01
+
+
+?
+Samsung SPC-4216P 286 at 12 MHz 1MB - 5MB RAM
+spc4216p/phoenix.bin or spc4216p/7101.u8 spc4216p/ac64.u10
+
+
+?
+Samsung SPC-4620P 286 at 12 MHz 1MB - 5MB RAM Built-in Korean ATI-28800
+spc4620p/31005h.u8 spc4620p/31005h.u10 spc4620p/svb6120a_font.rom spc4620p/31005h.u8 spc4620p/31005h.u10
+
+
+?
+Tulip AT Compact 286 640KB - 16MB RAM
+tulip_tc7/tc7be.bin tulip_tc7/tc7bo.bin
+
+
+
+386 based
+
+
+
+
+
+
+1987
+IBM PS/2 Model 80 [5] 386DX at 20 MHz 1MB - 12MB RAM Built-in VGA MCA bus
+i8580111/15f6637.bin i8580111/15f6639.bin
+
+
+1988
+ECS 386/32 386DX at 20 MHz 1MB - 16MB RAM
+ecs386_32/386_32_even.bin ecs386_32/386_32_odd.bin
+
+
+1989
+IBM PS/2 Model 70 (type 3) [5] 386DX at 25 MHz 2MB - 16MB RAM Built-in VGA MCA bus
+ibmps2_m70_type3/70-a_even.bin ibmps2_m70_type3/70-a_odd.bin
+
+
+1989
+Compaq Deskpro 386 386DX at 20 MHz 1MB - 15MB RAM
+deskpro386/109592-005.u11.bin deskpro386/109591-005.u13.bin
+
+
+1989
+Epson PC AX3 386SX at 16 MHz 256KB - 16MB RAM
+epson_pcax3/EVAX3 epson_pcax3/ODAX3
+
+
+1989
+IBM PS/2 Model 55SX 386SX at 16 MHz 1MB - 8MB RAM Built-in VGA MCA bus
+i8555081/33f8146.zm41 i8555081/33f8145.zm40
+
+
+1990
+DTK 386SX clone 386SX 512KB - 16MB RAM
+dtk386/3cto001.bin
+
+
+1990
+IBM PS/1 Model 2121 [5] 386SX at 20 MHz 1MB - 16MB RAM Built-in VGA
+ibmps1_2121/fc0000.bin
+
+
+1990
+Samsung SPC-6000A 386DX 1MB - 32 MB RAM
+spc6000a/3c80.u27 spc6000a/9f80.u26
+
+
+1992
+Acermate 386SX/25N [5] 386SX at 25 MHz 2MB - 16MB RAM Built-in Oak SVGA
+acer386/acer386.bin acer386/oti067.bin
+
+
+1992
+Amstrad MegaPC [2] [5] 386SX at 25 MHz 1MB - 16MB RAM Built-in VGA
+megapc/41651-bios lo.u18 megapc/211253-bios hi.u19
+
+
+1992
+Commodore SL386SX-25 [5] 386SX at 25 MHz 1MB - 16MB RAM Built-in AVGA2
+cbm_sl386sx25/f000.bin cbm_sl386sx25/c000.bin
+
+
+1992
+Packard Bell Legend 300SX 386SX at 16 MHz 1MB - 16MB RAM
+pb_l300sx/pb_l300sx.bin
+
+
+1992
+Samsung SPC-6033P 386SX at 33 MHz 2MB - 12 MB RAM
+spc6033p/phoenix.bin spc6033p/svb6120a_font.rom
+
+
+1994
+AMI 386DX clone 386DX at 40 MHz 1MB - 32MB RAM
+ami386dx/opt495sx.ami
+
+
+1994
+AMI 386SX clone 386SX at 25 MHz 1MB - 16MB RAM
+ami386/ami386.bin
+
+
+1994
+MR 386DX clone This is a generic 386DX clone with an MR BIOS
+mr386dx/opt495sx.mr
+
+
+?
+KMX-C-02 386SX 512KB - 16MB RAM
+kmxc02/3ctm005.bin
+
+
+
+486 based
+
+
+
+
+
+
+1990
+IBM PS/2 Model 70 (type 4) [3] 2MB - 16MB RAM Built-in VGA MCA bus
+486DX at 25 MHz
+ibmps2_m70_type3/70-a_even.bin ibmps2_m70_type3/70-a_odd.bin
+
+
+1993
+AMI 486 clone 1MB - 32MB RAM
+486 at 16-66 MHz
+ami486/ami486.bin
+
+
+1993
+Elonex PC-425X [5] 1MB - 256MB RAM Built-in Trident TGUI9440CXi
+486SX at 25 MHz
+elx_pc425x/elx_pc425x.bin or elx_pc425x/elx_pc425x_bios.bin elx_pc425x/elx_pc425x_vbios.bin
+
+
+1993
+IBM PS/1 Model 2133 (EMEA 451) 2MB - 64MB RAM Built-in Cirrus Logic GD5426
+486SX at 25 MHz
+ibmps1_2133/PS1_2133_52G2974_ROM.bin
+
+
+1993
+Packard Bell PB410A [5] 1MB - 64MB RAM Built-in HT-216 video
+486 at 25-120 MHzAm5x86 at 133-160 MHzCx5x86 at 100-133 MHzPentium Overdrive at 63-83 MHz
+pb410a/PB410A.080337.4ABF.U25.bin
+
+
+1994
+AMI WinBIOS 486 clone 1MB - 32MB RAM
+486 at 16-66 MHz
+win486/ali1429g.amw
+
+
+1995
+Award SiS 496/497 1MB - 64MB RAM
+486 at 16-120 MHzAm5x86 at 133-160 MHzCx5x86 at 100-133 MHzPentium Overdrive at 63-83 MHz
+sis496/sis496-1.awa
+
+
+
+Pentium based
+
+
+
+
+
+
+1994
+Intel Premiere/PCI (Batman's Revenge) 1MB - 128MB RAM
+Pentium at 60-66 MHzPentium Overdrive at 120-133 MHz
+revenge/1009af2_.bi0 revenge/1009af2_.bi1
+
+
+1995
+Intel Advanced/EV (Endeavor) [4] 1MB - 128MB RAM
+Pentium at 75-133 MHzPentium Overdrive at 125-200 MHz
+endeavor/1006cb0_.bi0 endeavor/1006cb0_.bi1
+
+
+1995
+Intel Advanced/ZP (Zappa) 1MB - 128MB RAM
+Pentium at 75-133 MHzPentium Overdrive at 125-200 MHz
+zappa/1006bs0_.bio zappa/1006bs0_.bi1
+
+
+1995
+Packard Bell PB520R (Robin LC) [5] 1MB - 128MB RAM Built-in Cirrus Logic GD-5434
+Pentium at 60-66 MHzPentium Overdrive at 120-133 MHz
+pb520r/1009bc0r.bio pb520r/1009bc0r.bi1 pb520r/gd5434.bin
+
+
+1995
+Packard Bell PB570 (Hillary) [5] 1MB - 128MB RAM Built-in Cirrus Logic GD-5430
+Pentium at 75-133 MHzPentium Overdrive at 125-200 MHz
+pb570/1007by0r.bio pb570/1007by0r.bi1 pb570/gd5430.bin
+
+
+1996
+ASUS P/I-P55TVP4 1MB - 128MB RAM
+Pentium at 75-200 MHzPentium MMX at 166-233 MHzMobile Pentium MMX at 120-300 MHzCyrix 6x86 at PR90(80 MHz) -PR200(200 MHz) Cyrix 6x86MX/MII at PR166(133 MHz) -PR400(285 MHz) IDT WinChip at 75-240 MHzIDT Winchip 2 at 200-240 MHzIDT Winchip 2A at 200-233 MHzAMD K6 at 166-300 MHzAMD K6-2 (AFR-66) at 233-300 MHz
+p55tvp4/tv5i0204.awd
+
+
+1996
+ASUS P/I-P55T2P4 1MB - 512MB RAM
+Pentium at 75-200 MHzPentium MMX at 166-233 MHzMobile Pentium MMX at 120-300 MHzCyrix 6x86 at PR90(80 MHz) -PR200(200 MHz) Cyrix 6x86MX/MII at PR166(133 MHz) -PR400(285 MHz) IDT WinChip at 75-240 MHzIDT Winchip 2 at 200-240 MHzIDT Winchip 2A at 200-233 MHzAMD K6 at 166-300 MHzAMD K6-2 (AFR-66) at 233-300 MHz
+p55t2p4/0207_j2.bin
+
+
+1996
+Award 430VX PCI 1MB - 128MB RAM
+Pentium at 75-200 MHzPentium MMX at 166-233 MHzMobile Pentium MMX at 120-300 MHzCyrix 6x86 at PR90(80 MHz) -PR200(200 MHz) Cyrix 6x86MX/MII at PR166(133 MHz) -PR400(285 MHz) IDT WinChip at 75-240 MHzIDT Winchip 2 at 200-240 MHzIDT Winchip 2A at 200-233 MHzAMD K6 at 166-300 MHzAMD K6-2 (AFR-66) at 233-300 MHz
+430vx/55xwuq0e.bin
+
+
+1996
+Itautec Infoway Multimidia 8MB - 128MB RAM
+Pentium at 75-133 MHzPentium Overdrive at 125-200 MHz
+infowaym/1006bs0_.bio infowaym/1006bs0_.bi1
+
+
+1997
+Epox P55-VA 1MB - 128MB RAM
+Pentium at 75-200 MHzPentium MMX at 166-233 MHzMobile Pentium MMX at 120-300 MHzCyrix 6x86 at PR90(80 MHz) -PR200(200 MHz) Cyrix 6x86MX/MII at PR166(133 MHz) -PR400(285 MHz) IDT WinChip at 75-240 MHzIDT Winchip 2 at 200-240 MHzIDT Winchip 2A at 200-233 MHzAMD K6 at 166-300 MHzAMD K6-2 (AFR-66) at 233-300 MHz
+p55va/va021297.bin
+
+
+
+Super Socket 7 based
+
+
+
+
+
+
+1998
+FIC VA-503+ 1MB - 512MB RAM
+AMD K6 at 166-300 MHzAMD K6-2 at 233-550 MHzAMD K6-2+ at 450-550 MHzAMD K6-III at 400-450 MHzAMD K6-III+ at 400-500 MHzPentium at 75-200 MHzPentium MMX at 166-233 MHzMobile Pentium MMX at 120-300 MHzCyrix 6x86 at PR90(80 MHz) -PR200(200 MHz) Cyrix 6x86MX/MII at PR166(133 MHz) -PR400(285 MHz) IDT WinChip at 75-240 MHzIDT WinChip2 at 200-250 MHzIDT Winchip 2A at PR200(200 MHz) -PR300(250 MHz)
+fic_va503p/je4333.bin
+
+
+
+Socket 8 based
+
+
+
+
+
+
+1996
+Intel VS440FX 8MB - 256 MB RAM
+Pentium Pro at 150-200 MHzPentium II Overdrive at 300-333 MHz
+vs440fx/1018CS1_.BI1 vs440fx/1018CS1_.BI2 vs440fx/1018CS1_.BI3 vs440fx/1018CS1_.BIO vs440fx/1018CS1_.RCV
+
+
+
+Slot 1 based
+
+
+
+
+
+
+1998
+Gigabyte GA-686BX 8MB - 512MB RAM
+Pentium II at 233-450 MHzCeleron at 266-533 MHzCyrix III at 500 MHz
+ga686bx/6BX.F2a
+
+
+
+Additional Notes
+[1] Toshiba Button Mapping : PCem maps [Fn] to right-Ctrl and right-Alt. The following functions are supported: Key Combo | Function ---|--- Fn + Num Lock | toggle numpad Fn + Home | Internal LCD display Fn + Page Down | Turbo on Fn + Right | Toggle LCD font Fn + End | External CRT display Fn + SysRQ | Toggle window
+[2] Amstrad MegaPC (386SX) : The original machine had a built-in Sega MegaDrive. This is not emulated in PCem.
+[3] IBM PS/2 Model 70 (type 4) (486DX) : PCem's FPU emulation is not bit accurate and can not pass IBM's floating point tests. As a result, this machine will always print 12903 and 162 errors on bootup. These can be ignored - F1 will boot the machine.
+[4] Intel Advanced/EV (Endeavor) (Pentium) : The real board has a Sound Blaster 16 onboard and optionally an S3 Trio64V+. Neither are emulated as onboard devices.
+[5] Some systems have fixed graphics adapters: ** = Can use external video card.
+
+
+
+
+
+
+Amstrad MegaPC
+Paradise 90C11
+A development of the PVGA1 with 512KB VRAM
+✔
+
+
+Acer 386SX/25N
+Oak OTI-067
+Another 512KB SVGA clone
+✔
+
+
+Amstrad PC1512
+CGA
+Has a new mode (640x200x16)
+X
+
+
+Amstrad PC1640
+Paradise EGA
+
+✔
+
+
+Amstrad PC2086/PC3086
+Paradise PVGA1
+An early SVGA clone with 256KB VRAM
+✔
+
+
+Amstrad PPC512/640
+CGA/MDA
+Outputs to 640x200 plasma display
+✔
+
+
+Commodore SL386SX-25
+AVGA2
+256KB - 512KB VRAM
+X
+
+
+Elonex PC-425X
+Trident TGUI9400CXi
+512KB VRAM
+X
+
+
+IBM PCjr
+CGA
+Has various new modes: 160x200 x 16 320x200 x 16 640x200 x 4
+X
+
+
+IBM PS/1 Model 2011
+Stock VGA
+256KB VRAM
+X
+
+
+IBM PS/1 Model 2121
+Basic (and unknown) SVGA
+256KB VRAM
+X
+
+
+IBM PS/2 machines
+Stock VGA
+256KB VRAM
+X
+
+
+Olivetti M24 [6]
+CGA
+Has double-res text modes + 640x400 mode
+X
+
+
+Packard Bell PB410A
+Headland HT-216
+
+✔
+
+
+Packard Bell PB520R
+Cirrus Logic GD-5434
+
+✔
+
+
+Packard Bell PB570
+Cirrus Logic GD-5430
+
+✔
+
+
+Sinclair PC200
+CGA
+Can output to TV @ 50hz (UK)
+✔
+
+
+Tandy 1000
+Clone of PCjr video
+Widely supported in 80s games
+X
+
+
+Tandy 1000 SL/2
+Improved Tandy 1000
+Has support for 640x200x16
+X
+
+
+Toshiba T-series
+CGA
+Outputs to built-in LCD or plasma display
+X
+
+
+
+[6] Olivetti M24 (display) : I haven't seen a dump of the font ROM for this yet, so if one is not provided the MDA font will be used - which looks slightly odd as it is 14-line instead of 16-line.
+
+
+Graphics Cards
+Basic cards
+
+
+
+
+
+
+MDA (1981)
+80x25 monochrome text
+(none)
+
+
+CGA (1981)
+40x25 and 80x25 text 320x200 in 4 colours 620x200 in 2 colours Supports composite output for ~16 colours.
+(none)
+
+
+Hercules (1982)
+80x25 monochrome text 720x348 in monochrome
+(none)
+
+
+Plantronics ColorPlus
+An enhanced CGA board with support for 320x200x16 and 640x200x4
+(none)
+
+
+Wyse WY-700
+A CGA-compatible board with support for a 1280x800 mode
+(none)
+
+
+MDSI Genius
+Mono portrait board with support for a 728x1008 mode
+8x12.bin
+
+
+IBM EGA (1984)
+Text up to 80x43 Graphics up to 640x350 in 16 colours
+ibm_6277356_ega_card_u44_27128.bin
+
+
+ATI EGA Wonder 800+
+An enhanced EGA-compatible board with support for up to 800x600 in 16 colours
+ATI EGA Wonder 800+ N1.00.BIN
+
+
+Hercules InColor
+An enhanced Hercules with a custom 720x350 16 colour mode
+(none)
+
+
+
+Unaccelerated (S)VGA cards
+
+
+
+
+
+
+ATI Korean VGA
+ATI-28800 based. 512KB VRAM Supports up to 8-bit colour Korean font support
+atikorvga.bin ati_ksc5601.rom
+
+
+ATI VGA Edge-16
+ATI-18800 based 512KB VRAM Supports up to 8-bit colour
+vgaedge16.vbi
+
+
+ATI VGA Charger
+ATI-28800 based 512KB VRAM Supports up to 8-bit colour
+bios.bin
+
+
+AVGA2
+Also known as Cirrus Logic GD5402 256KB - 512KB VRAM Supports up to 8-bit colour
+avga2vram.vbi
+
+
+IBM VGA (1987)
+256KB VRAM Text up to 80x50 Graphics up to 320x200 in 256 colours or 640x480 in 16 colours
+ibm_vga.bin
+
+
+Kasan Hangulmadang-16
+ET4000AX based 1MB VRAM Supports up to 8-bit colour Korean font support
+et4000_kasan16.bin kasan_ksc5601.rom
+
+
+OAK OTI-037C
+256KB VRAM Supports up to 8-bit colour
+oti037/bios.bin
+
+
+OAK OTI-067
+256KB - 512KB VRAM Supports up to 8-bit colour
+oti067/bios.bin
+
+
+Olivetti GO481 (Paradise PVGA1A)
+256KB VRAM Supports up to 8-bit colour
+oli_go481_lo.bin oli_go481_hi.bin
+
+
+Trident 8900D SVGA
+256KB - 1MB VRAM Supports up to 24-bit colour
+trident.bin
+
+
+Trident 9000B SVGA
+512KB VRAM Supports up to 8-bit colour
+tvga9000b/BIOS.BIN
+
+
+Trident TGUI9400CXi
+1MB - 2MB VRAM Supports up to 24-bit colour
+9440.vbi
+
+
+Trigem Korean VGA
+ET4000AX based 1MB VRAM Supports up to 8-bit colour Korean font support
+tgkorvga.bin tg_ksc5601.rom
+
+
+Tseng ET4000AX SVGA
+1MB VRAM Supports up to 8-bit colour
+et4000.bin
+
+
+
+2D Accelerated SVGA cards
+
+
+
+
+
+
+ATI Graphics Pro Turbo
+Mach64GX based 1MB - 4MB VRAM
+mach64gx/bios.bin
+
+
+ATI Video Xpression
+Mach64VT2 based 2MB - 4MB VRAM Has video acceleration
+atimach64vt2pci.bin
+
+
+Cirrus Logic GD-5428
+1MB - 2MB VRAM
+Machspeed_VGA_GUI_2100_VLB.vbi
+
+
+Cirrus Logic GD-5429
+1MB - 2MB VRAM
+5429.vbi
+
+
+Cirrus Logic GD-5430
+1MB - 2MB VRAM
+gd5430/pci.bin
+
+
+Cirrus Logic GD-5434 [1]
+2MB - 4MB VRAM
+gd5434.bin
+
+
+Diamond Stealth 32 SVGA
+ET4000/W32p based 1MB - 2MB VRAM
+et4000w32.bin
+
+
+IBM 1MB SVGA Adapter/A
+Cirrus Logic GD5428 based 1 MB VRAM Only supported on PS/2 models
+SVGA141.ROM
+
+
+Number Nine 9FX
+S3 Trio64 based 1MB - 2MB VRAM
+s3_764.bin
+
+
+Paradise Bahamas 64
+S3 Vision864 based 1MB - 4MB VRAM
+bahamas64.bin
+
+
+Phoenix S3 Trio32
+S3 Trio32 based 512KB - 2MB VRAM
+86c732p.bin
+
+
+Phoenix S3 Trio64
+S3 Trio64 based 1MB - 4MB VRAM
+86c764x1.bin
+
+
+Trident TGUI9440
+1MB - 2MB VRAM
+9440.vbi
+
+
+
+3D Accelerated SVGA cards
+
+
+
+
+
+
+3DFX Voodoo Banshee (reference)
+Voodoo Banshee based 8MB - 16MB VRAM
+pci_sg.rom
+
+
+3DFX Voodoo 3 2000
+Voodoo 3 based 16MB VRAM
+voodoo3_2000/2k11sd.rom
+
+
+3DFX Voodoo 3 3000
+Voodoo 3 based 16MB VRAM
+voodoo3_3000/3k12sd.rom
+
+
+Creative Labs 3D Blaster Banshee
+Voodoo Banshee based 16MB VRAM
+blasterpci.rom
+
+
+Diamond Stealth 3D 2000 [2]
+S3 ViRGE/325 based 2MB - 4MB VRAM
+s3virge.bin
+
+
+S3 ViRGE/DX [3]
+S3 ViRGE/DX based 2MB - 4MB VRAM
+86c375_1.bin
+
+
+
+3D only cards
+
+
+
+
+
+
+3DFX Voodoo Graphics [4]
+3D accelerator. Widely supported in late 90s games.
+
+
+Obsidian SB50 [5]
+Voodoo with 2 TMUs
+
+
+3DFX Voodoo 2 [6]
+Improved Voodoo Graphics Higher clocks 2 TMUs Triangle setup, etc.
+
+
+
+Additional Notes
+[1] Cirrus Logic GD-5434 : Real chip also supports 1MB configurations, however this is not currently supported in PCem.
+[2] Diamond Stealth 3D 2000 : PCem emulates the ViRGE S3D engine in software. This works with most games I tried, but there may be some issues. The Direct3D drivers for the /325 are fairly poor (often showing as missing triangles), so use of the /DX instead is recommended.
+[3] S3 ViRGE/DX : The drivers that come with Windows are similar to those for the /325, however better ones do exist (try the 8-21-1997 version). With the correct drivers, many early Direct3D games work okay (if slowly).
+[4] 3DFX Voodoo Graphics : PCem emulates this in software. The emulation is a lot faster than in v10 (thanks to a new dynamic recompiler) and should be capable of hitting Voodoo 1 performance on most machines when two render threads are used. As before, the emulated CPU is the bottleneck for most games. PCem can emulate 6 and 8 MB configurations, but defaults to 4 MB for compatibility. It can also emulate the screen filter present on the original card, though this does at present have a noticeable performance hit. Almost everything I've tried works okay, with a very few exceptions - Screamer 2 and Rally have serious issues.
+[5] Obsidian SB50 : Drivers for this are a bit limited - the official drivers don't support 2 TMUs in Direct3D.
+[6] 3DFX Voodoo 2 : PCem can emulate both 8 and 12 MB configurations. It can also emulate 6 and 10 MB configurations (with 2MB framebuffer memory), which were never sold into the PC market but do exist for arcade systems.
+
+
+Sound Cards
+
+
+
+
+
+
+PC speaker
+The standard beeper on all PCs. Supports samples/RealSound.
+
+
+Tandy PSG
+The Texas Instruments chip in the PCjr and Tandy 1000. Supports 3 voices plus noise. I reused the emulator in B-em for this (slightly modified). PCem emulates the differences between the SN76496 (PCjr and Tandy 1000), and the NCR8496 (currently assigned to the Tandy 1000HX). Maniac Mansion and Zak McKraken will only sound correct on the latter.
+
+
+Tandy PSSJ
+Used on the Tandy 1000SL/2, this clones the NCR8496, adding an addition frequency divider (did any software actually use this?) and an 8-bit DAC.
+
+
+PS/1 audio card
+An SN76496 clone plus an 8-bit DAC. The SN76496 isn't at the same address as PCjr/Tandy, so most software doesn't support it.
+
+
+Gameblaster
+The Creative Labs Gameblaster/Creative Music System, Creative's first sound card introduced in 1987. Has two Philips SAA1099, giving 12 voices of square waves plus 4 noise voices. In stereo!
+
+
+Adlib
+Has a Yamaha YM3812, giving 9 voices of 2 op FM, or 6 voices plus a rhythm section. PCem uses the DOSBox dbopl emulator.
+
+
+Adlib Gold
+OPL3 with YM318Z 12-bit digital section. Possibly some bugs (not a lot of software to test). The surround module is now emulated.
+
+
+Sound Blaster [1]
+See linked note for more details.
+
+
+Gravis Ultrasound
+32 voice sample playback. Port address is fixed to 240, IRQ and DMA can be changed from the drivers. Emulation is improved significantly over previous versions.
+
+
+Windows Sound System
+16-bit digital + OPL3. Note that this only emulates WSS itself, and should not be used with drivers from compatible boards with additional components (eg Turtle Beach Monte Carlo)
+
+
+Aztech Sound Galaxy Pro 16 AB (Washington)
+SB compatible + WSS compatible
+
+
+Innovation SSI-2001
+SID6581. Emulated using resid-fp. Board is fixed to port 280.
+
+
+Ensoniq AudioPCI (ES1371) Sound Blaster PCI 128
+Basic PCI sound card. Emulates Sound Blaster in software.
+
+
+
+Additional Notes
+[1] Sound Blaster : Several Sound Blasters are emulated.
+
+SB v1.0 - The original. Limited to 22khz, and no auto-init DMA (can cause crackles sometimes).
+SB v1.5 - Adds auto-init DMA
+SB v2.0 - Upped to 41khz
+SB Pro v1.0 - Stereo with twin OPL2 chips.
+SB Pro v2.0 - Stereo with OPL 3 chip
+SB 16 - 16 bit stereo
+SB AWE32 - SB 16 + wavetable MIDI. This requires a ROM dump from a real AWE32.
+
+All cards are set to Address 220, IRQ 7 and DMA 1 (and High DMA 5). IRQ and DMA can be changed for the SB16 & AWE32 in the drivers. The relevant SET line for autoexec.bat is SET BLASTER = A220 I7 D1 Tx - where Tx is T1 for SB v1.0, T3 for SB v2.0, T4 for SB Pro, and T6 for SB16.
+AWE32 requires a ROM dump called awe32.raw. AWE-DUMP is a utility which can get a dump from a real card. Most EMU8000 functionality should work, however filters are not correct and reverb/chorus effects are not currently emulated.
+
+
+HDD Controller Cards
+
+
+
+
+
+
+MFM
+Fixed Disk Adapter (Xebec)
+MFM controller originally included in the IBM XT. This controller only supports HD types 0, 2, 13, and 16.
+ibm_xebec_62x0822_1985.bin
+
+
+MFM
+DTC 5150X
+8-bit MFM controller. To configure drive types, run DEBUG.EXE and enter g=c800:5.
+dtc_cxd21a.bin
+
+
+MFM
+AT Fixed Disk Adapter
+MFM controller originally included in the IBM AT. Supported by all AT-compatible BIOSes.
+(none)
+
+
+ESDI
+Western Digital WD1007V-SE1
+16-bit ESDI controller
+62-000279-061.bin
+
+
+ESDI
+IBM ESDI Fixed Disk Controller
+MCA ESDI controller. Only supported on PS/2 models.
+90x8969.bin 90x8970.bin
+
+
+IDE
+Standard IDE
+Standard IDE controller. Supported by all AT-compatible BIOSes. Use this if in any doubt!
+(none)
+
+
+IDE
+XTIDE
+8-bit IDE controller. The BIOS is available here . v2.0.0 beta 1 is the version I've mostly tested. v2.0.0 beta 3 is known to have some issues.
+ide_xt.bin
+
+
+IDE
+XTIDE (AT)
+16-bit IDE controller.
+ide_at.bin
+
+
+IDE
+XTIDE (PS/1)
+IDE controller for the PS/1 model 2033. For this machine you will need BIOS version v1.1.5. The PS/1 is a bit fussy with XTIDE, and I've found that it works best when the XTIDE configuration has 'Full Operating Mode' disabled.
+ide_at_1_1_5.bin
+
+
+SCSI
+Longshine LCS-6821N
+8-bit SCSI controller.
+Longshine LCS-6821N - BIOS version 1.04.bin
+
+
+SCSI
+Rancho RT1000B
+8-bit SCSI controller.
+Rancho_RT1000_RTBios_version_8.10R.bin
+
+
+SCSI
+Trantor T130B
+8-bit SCSI controller.
+trantor_t130b_bios_v2.14.bin
+
+
+SCSI
+IBM SCSI Adapter with Cache
+MCA SCSI controller. Only supported on PS/2 models.
+92F2244.U68 92F2245.U69
+
+
+SCSI
+Adaptec AHA-1542C
+16-bit SCSI controller.
+adaptec_aha1542c_bios_534201-00.bin
+
+
+SCSI
+BusLogic BT-545S
+16-bit SCSI controller.
+BusLogic_BT-545S_U15_27128_5002026-4.50.bin
+
+
+
+
+
+Misc Cards
+
+
+
+
+
+
+Serial mouse
+A Microsoft compatible serial mouse on COM1. Compatible drivers are all over the place for this.
+
+
+M24 mouse
+I haven't seen a DOS mouse driver for this yet but the regular scancode mode works as does the Windows 1.x driver.
+
+
+PC1512 mouse
+The PC1512's perculiar quadrature mouse. You need Amstrad's actual driver for this one.
+
+
+PS/2 mouse
+A standard 2 button PS/2 mouse. As with serial, compatible drivers are common.
+
+
+Microsoft PS/2 Intellimouse
+A PS/2 mouse with mouse wheel.
+
+
+ATAPI CD-ROM
+Works with OAKCDROM.SYS, VDD-IDE.SYS, and the internal drivers of every OS I've tried.
+
+
+
+
+
diff --git a/readme.txt b/readme.txt
deleted file mode 100644
index 6441056..0000000
--- a/readme.txt
+++ /dev/null
@@ -1,1442 +0,0 @@
-PCem v14
-
-PCem is licensed under the GPL, see COPYING for more details.
-
-Changes since v13.1:
-
-- New machines added - Compaq Portable Plus, Compaq Portable II, Elonex PC-425X,
- IBM PS/2 Model 70 (types 3 & 4), Intel Advanced/ZP, NCR PC4i, Packard Bell Legend 300SX,
- Packard Bell PB520R, Packard Bell PB570, Thomson TO16 PC, Toshiba T1000, Toshiba T1200, Xi8088
-- New graphics cards added - ATI Korean VGA, Cirrus Logic CL-GD5429, Cirrus Logic CL-GD5430,
- Cirrus Logic CL-GD5435, OAK OTI-037, Trident TGUI9400CXi
-- New network adapters added - Realtek RTL8029AS
-- Iomega Zip drive emulation
-- Added option for default video timing
-- Added dynamic low-pass filter for SB16/AWE32 DSP playback
-- Can select external video card on some systems with built-in video
-- Can use IDE hard drives up to 127 GB
-- Can now use 7 SCSI devices
-- Implemented CMPXCHG8B on Winchip. Can now boot Windows XP on Winchip processors
-- CD-ROM emulation on OS X
-- Tweaks to Pentium and 6x86 timing
-- Numerous bug fixes - fixes Wing Commander : Privateer, Wing Commander III, Wings of Fury,
- Zone Raiders, NFL Blitz 2000, Joe Montana Football, SB16 with Earthworm Jim, SB16 with SimCity
- 2000, SB16 with Visual Player 2.0, AHA-1542C with Solaris 2.4, Voodoo 2 with FMV in Urban Chaos,
- SB2.0 with Syndicate, floppy on early Linux kernels, clicking ADPCM sound playback, varying speed
- in Desert Strike, keyboard hang on KMX-C-02, S3 video cards with Linux and OS/2 Warp, AudioPCI
- hangs on Windows 2000/XP, OS/2 v2.0 on machines with remapped memory (eg PS/2), OS/2 v2.0 IO
- performance with PS/2 ESDI, etc etc
-
-Thanks to darksabre76, dns2kv2, EluanCM, Greatpsycho, ja've, John Elliott, leilei and nerd73 for
-contributions towards this release.
-
-
-PCem emulates the following machines:
-
-8088 based :
-
-AMI XT clone (1989)
-
-8088 at 8+ MHz, 64-640kb RAM.
-
-ROM files needed:
- amixt\ami_8088_bios_31jan89.bin
-
-
-Atari PC3 (19xx)
-
-8088 at 8 MHz, 640kb RAM.
-
-ROM files needed:
- ataripc3/AWARD_ATARI_PC_BIOS_3.08.BIN
-
-
-Compaq Portable Plus (1983)
-
-8088 at 4.77 MHz, 128-640kb RAM.
-
-ROM files needed:
- compaq_pip/Compaq Portable Plus 100666-001 Rev C.bin
-
-
-DTK Clone XT (1986)
-
-8088 at 8/10 MHz, 64kb-640kb RAM.
-
-ROM files needed:
- dtk/dtk_erso_2.42_2764.bin
-
-
-(c)Anonymous Generic Turbo XT BIOS (1988?)
-
-8088 at 8+ MHz, 64-640kb RAM.
-
-ROM files needed:
- genxt\pcxt.rom
-
-
-IBM PC (1981)
-
-8088 at 4.77 MHz, 16-640kb RAM (PCem emulates minimum 64kb)
-
-ROM files needed:
- ibmpc\pc102782.bin
- ibmpc\basicc11.f6
- ibmpc\basicc11.f8
- ibmpc\basicc11.fa
- ibmpc\basicc11.fc
-
-
-IBM PCjr (1984)
-
-8088 at 4.77 MHz, 64-640kb RAM (PCem emulates minimum 128kb), built-in 16 colour graphics, 3 voice sound.
-Not generally PC compatible.
-
-ROM files needed:
- ibmpcjr\bios.rom
-
-
-IBM XT (1983)
-
-8088 at 4.77 MHz, 64-640kb RAM
-
-ROM files needed:
- ibmxt\5000027.u19
- ibmxt\1501512.u18
-
-
-Juko XT clone (1988)
-
-ROM files needed:
-
-jukopc\000o001.bin
-
-
-NCR PC4i (1985)
-
-8088 at 4.77 MHz, 256-640kb RAM
-
-ROM files needed:
- ncr_pc4i/NCR_PC4i_BIOSROM_1985.BIN
-
-
-Phoenix XT clone (1986)
-
-8088 at 8/10 MHz, 64kb-640kb RAM.
-
-ROM files needed:
- pxxt\000p001.bin
-
-
-Schneider Euro PC (1988)
-
-8088 at 9.54 MHz, 512-640kb RAM.
-
-ROM files needed:
- europc\50145
- europc\50146
-
-
-Tandy 1000 (1984)
-
-8088 at 4.77 MHz, 128kb-640kb RAM, built-in 16 colour graphics + 3 voice sound
-
-ROM files needed:
- tandy\tandy1t1.020
-
-
-Tandy 1000HX (1987)
-
-8088 at 7.16 MHz, 256-640kb RAM, built-in 16 colour graphics + 3 voice sound.
-Has DOS 2.11 in ROM.
-A Tandy 1000 with a faster 7.16 MHz 8088, and DOS in ROM.
-
-ROM files needed:
- tandy1000hx\v020000.u12
-
-
-Thomson TO16 PC (1987)
-
-8088 at 9.54 MHz, 512-640kb RAM.
-
-ROM files needed:
- to16_pc/TO16_103.bin
-
-
-Toshiba T1000 (1987)
-
-8088 at 4.77 MHz, 512-1024 kb RAM, CGA on built-in LCD.
-
-PCem maps [Fn] to right-Ctrl and right-Alt. The following functions are supported :
- Fn + Num Lock - toggle numpad
- Fn + Home - Internal LCD display
- Fn + Page Down - Turbo on
- Fn + Right - Toggle LCD font
- Fn + End - External CRT display
- Fn + SysRQ - Toggle window
-
-ROM files needed:
- t1000/t1000.rom
- t1000/t1000font.rom
-
-
-VTech Laser Turbo XT (1987)
-
-8088 at 10 MHz, 640kb RAM
-
-ROM files needed:
-
-ltxt\27c64.bin
-
-
-Xi8088 (2015)
-
-8088 at 4.77 - 13.33 MHz, 640kb RAM
-
-ROM files needed:
- xi8088/bios-xi8088.bin
-
-
-8086 based :
-
-
-Amstrad PC1512 (1986)
-
-8086 at 8 MHz, 512kb-640kb RAM, enhanced CGA (supports 640x200x16), custom mouse port.
-
-ROM files needed:
- pc1512\40043.v1
- pc1512\40044.v2
- pc1512\40078.ic127
-
-
-Amstrad PC1640 (1987)
-
-8086 at 8 MHz, 640kb RAM, built-in Paradise EGA, custom mouse port.
-
-ROM files needed:
- pc1640\40043.v3
- pc1640\40044.v3
- pc1640\40100
-
-
-Amstrad PC2086 (1989)
-
-8086 at 8 MHz, 640kb, built-in VGA.
-
-ROM files needed:
- pc2086\40179.ic129
- pc2086\40180.ic132
- pc2086\40186.ic171
-
-
-Amstrad PC3086 (1990)
-
-8086 at 8 MHz, 640kb, built-in VGA.
-
-ROM files needed:
- pc3086\fc00.bin
- pc3086\c000.bin
-
-
-Olivetti M24 (1984)
-
-8086 at 8 MHz, 128kb-640kb RAM, built-in enhanced CGA (supports 640x400x2).
-
-ROM files needed:
- olivetti_m24\olivetti_m24_version_1.43_low.bin
- olivetti_m24\olivetti_m24_version_1.43_high.bin
-
-
-Sinclair PC200/Amstrad PC20 (1988)
-
-8086 at 8 MHz, 512-640kb RAM, built-in CGA.
-
-ROM files needed:
- pc200\pc20v2.0
- pc200\pc20v2.1
- pc200\40109.bin
-
-
-Tandy 1000SL/2 (1989)
-
-8086 at 9.54 MHz, 512-768kb RAM, built-in 16 colour graphics + 4 voice sound.
-
-ROM files needed:
- tandy1000sl2\8079047.hu1
- tandy1000sl2\8079048.hu2
-
-
-Toshiba T1200 (1987)
-
-8086 at 9.54 MHz, 1-2 MB RAM, CGA on built-in LCD.
-
-PCem maps [Fn] to right-Ctrl and right-Alt. The following functions are supported :
- Fn + Num Lock - toggle numpad
- Fn + Home - Internal LCD display
- Fn + Page Down - Turbo on
- Fn + Right - Toggle LCD font
- Fn + End - External CRT display
- Fn + SysRQ - Toggle window
-
-ROM files needed:
- t1200/t1200_019e.ic15.bin
- t1200/t1000font.rom
-
-
-VTech Laser XT3 (1988)
-
-8086 at 10 MHz, 512-1152kb RAM.
-
-ROM files needed:
- lxt3\27c64d.bin
-
-
-
-286 based :
-
-
-AMI 286 clone (1990)
-
-286 at 8+ MHz, 512kb - 16MB RAM.
-
-ROM files needed:
- ami286\amic206.bin
-
-
-Award 286 clone (1990)
-
-286 at 8+ MHz, 512kb - 16MB RAM.
-
-ROM files needed:
- award286\award.bin
-
-
-Commodore PC30-III (1988)
-
-286 at 12 MHz, 512kb - 16MB RAM.
-
-ROM files needed:
- cmdpc30\commodore pc 30 iii even.bin
- cmdpc30\commodore pc 30 iii odd.bin
-
-
-Compaq Portable II (1986)
-
-286 at 8 MHz, 256kb-15MB RAM.
-
-ROM files needed:
- compaq_pii/109739-001.rom
- compaq_pii/109740-001.rom
-
-
-Dell System 200 (1990?)
-
-286 at 12 MHz, 640kb-16MB RAM.
-
-ROM files needed:
- dells200\dell0.bin
- dells200\dell1.bin
-
-
-Epson PC AX (1989)
-
-286, 256kb - 16MB RAM.
-
-ROM files needed :
- epson_pcax\EVAX
- epson_pcax\ODAX
-
-
-Epson PC AX2e (1989)
-
-286 at 12 MHz, 256kb - 16MB RAM.
-
-ROM files needed :
- epson_pcax2e\EVAX
- epson_pcax2e\ODAX
-
-
-GW-286CT GEAR
-
-286 at 8+ MHz, 512kb - 16MB RAM.
-
-ROM files needed:
-
- gw286ct/2ctc001.bin
-
-
-IBM AT (1984)
-
-286 at 6 or 8 MHz, 256kb-16mb RAM
-
-ROM files needed:
- ibmat\at111585.0
- ibmat\at111585.1
-
-
-IBM PS/1 Model 2011 (1990)
-
-286 at 10 MHz, 512kb-16MB RAM, built-in VGA, DOS 4.01 + GUI menu system in ROM.
-
-ROM files needed :
- ibmps1\f80000.bin
-
-
-IBM PS/2 Model 30-286 (1988)
-
-286 at 10 MHz, 1MB-16MB RAM, built-in VGA, MCA bus.
-
-ROM files needed :
- ibmps2_m30_286\33f5381a.bin
-
-
-IBM PS/2 Model 50 (1987)
-
-286 at 10 MHz, 1MB-16MB RAM, built-in VGA, MCA bus.
-
-ROM files needed :
- i8550021\90x7420.zm13
- i8550021\90x7423.zm14
- i8550021\90x7426.zm16
- i8550021\90x7429.zm18
-
-
-IBM XT Model 286 (1986)
-
-286 at 6 MHz, 256kb-16mb RAM
-
-ROM files needed :
- ibmxt286\BIOS_5162_21APR86_U34_78X7460_27256.BIN
- ibmxt286\BIOS_5162_21APR86_U35_78X7461_27256.BIN
-
-
-Samsung SPC-4200P
-
-286 at 12 MHz, 512kb - 2MB RAM
-
-ROM files needed :
-spc4200p\u8.01
-
-
-Samsung SPC-4216P
-
-286 at 12 MHz, 1MB - 5MB RAM
-
-ROM files needed :
- spc4216p\phoenix.bin
-or
- spc4216p\7101.u8
- spc4216p\ac64.u10
-
-
-Toshiba T3100e (1986)
-
-286 at 12 MHz, 1MB - 5MB RAM, CGA on gas-plasma display
-
-PCem maps [Fn] to right-Ctrl and right-Alt.
-
-ROM files needed :
- t3100e\t3100e_font.bin
- t3100e\t3100e.rom
-
-
-
-386SX based :
-
-
-Acermate 386SX/25N (1992?)
-
-386SX at 25 MHz, 2-16MB RAM, built-in Oak SVGA.
-
-ROM files needed :
- acer386\acer386.bin
- acer386\oti067.bin
-
-
-AMI 386SX clone (1994)
-
-386SX at 25 MHz, 1-16MB RAM.
-
-ROM files needed :
- ami386\ami386.bin
-
-
-Amstrad MegaPC (1992)
-
-386SX at 25 MHz, 1-16MB RAM, built-in VGA.
-
-The original machine had a built-in Sega MegaDrive. This is not emulated in PCem.
-
-ROM files needed :
- megapc\41651-bios lo.u18
- megapc\211253-bios hi.u19
-
-
-DTK 386SX clone (1990)
-
-386SX, 512kb - 16MB RAM.
-
-ROM files needed :
- dtk386\3cto001.bin
-
-
-Epson PC AX3 (1989)
-
-386SX at 16 MHz, 256kb-16MB RAM.
-
-ROM files needed :
- epson_pcax3\EVAX3
- epson_pcax3\ODAX3
-
-
-IBM PS/1 Model 2121 (1990)
-
-386SX at 20 MHz, 1MB-16MB RAM, built-in VGA.
-
-ROM files needed:
- ibmps1_2121\fc0000.bin
-
-
-IBM PS/2 Model 55SX (1989)
-
-386SX at 16 MHz, 1MB-8MB RAM, built-in VGA, MCA bus.
-
-ROM files needed :
- i8555081\33f8146.zm41
- i8555081\33f8145.zm40
-
-
-KMX-C-02
-
-386SX, 512kb-16MB RAM.
-
-ROM files needed :
- kmxc02\3ctm005.bin
-
-
-Packard Bell Legend 300SX (1992)
-
-386 SX at 16 MHz, 1-16MB RAM
-
-ROM files needed :
- pb_l300sx/pb_l300sx.bin
-
-
-
-386DX based :
-
-
-AMI 386DX clone (1994)
-
-386DX at 40 MHz, 1-32MB RAM.
-
-ROM files needed:
- ami386dx\opt495sx.ami
-
-
-Compaq Deskpro 386 (1989)
-
-386DX at 20 MHz, 1MB-15MB RAM.
-
-ROM files needed:
- deskpro386\109592-005.u11.bin
- deskpro386\109591-005.u13.bin
-
-
-IBM PS/2 Model 70 (type 3) (1989)
-
-386DX at 25 MHz, 2-16MB RAM, built-in VGA, MCA bus.
-
-ROM files needed :
- ibmps2_m70_type3/70-a_even.bin
- ibmps2_m70_type3/70-a_odd.bin
-
-
-IBM PS/2 Model 80 (1987)
-
-386DX at 20 MHz, 1MB-12MB RAM, built-in VGA, MCA bus.
-
-ROM files needed :
- i8580111\15f6637.bin
- i8580111\15f6639.bin
-
-
-MR 386DX clone (1994)
-This is a generic 386DX clone with an MR BIOS.
-
-ROM files needed:
-
-mr386dx\opt495sx.mr
-
-
-
-486 based :
-
-
-AMI 486 clone (1993)
-
-486 at 16-66 MHz, 1-32MB RAM.
-
-ROM files needed:
- ami486\ami486.bin
-
-
-AMI WinBIOS 486 clone (1994)
-
-486 at 16-66 MHz, 1-32MB RAM.
-
-ROM files needed:
- win486\ali1429g.amw
-
-
-Award SiS 496/497 (1995)
-
-486 at 16-120 MHz, Am5x86 at 133-160 MHz, Cx5x86 at 100-133 MHz, Pentium Overdrive
-at 63-83 MHz. 1-64MB RAM.
-
-ROM files needed:
- sis496\sis496-1.awa
-
-
-Elonex PC-425X (1993)
-
-486SX at 25 MHz, 1-256MB RAM, built-in Trident TGUI9440CXi
-
-ROM files needed:
- elx_pc425x/elx_pc425x.bin
-or
- elx_pc425x/elx_pc425x_bios.bin
- elx_pc425x/elx_pc425x_vbios.bin
-
-
-IBM PS/2 Model 70 (type 4) (1990)
-
-486DX at 25 MHz, 2-16MB RAM, built-in VGA, MCA bus.
-
-PCem's FPU emulation is not bit accurate and can not pass IBM's floating point tests. As a result,
-this machine will always print 12903 and 162 errors on bootup. These can be ignored - F1 will boot
-the machine.
-
-ROM files needed :
- ibmps2_m70_type3/70-a_even.bin
- ibmps2_m70_type3/70-a_odd.bin
-
-
-Pentium based :
-
-
-Award 430VX PCI (1996)
-
-Pentium at 75-200 MHz, Pentium MMX at 166-233 MHz, Mobile Pentium MMX at 120-300 MHz,
-Cyrix 6x86 at PR90(80 MHz)-PR200(200 MHz), Cyrix 6x86MX/MII at PR166(133 MHz)-
-PR400(285 MHz), IDT WinChip at 75-240 MHz. 1-128MB RAM (PCem allows up to 256).
-
-ROM files needed:
- 430vx\55xwuq0e.bin
-
-
-Intel Advanced/EV (Endeavor) (1995)
-
-Pentium at 75-133 MHz, Pentium Overdrive at 125-200 MHz, 1-128MB RAM.
-
-The real board has a Sound Blaster 16 onboard, and optionally an S3 Trio64V+. Neither
-are emulated as onboard devices.
-
-ROM files needed:
- endeavor\1006cb0_.bi0
- endeavor\1006cb0_.bi1
-
-
-Intel Advanced/ZP (Zappa) (1995)
-
-Pentium at 75-133 MHz, Pentium Overdrive at 125-200 MHz, 1-128MB RAM.
-
-ROM files needed:
- zappa/1006bs0_.bio
- zappa/1006bs0_.bi1
-
-
-Intel Premiere/PCI (Batman's Revenge) (1994)
-
-Pentium at 60-66 MHz, Pentium OverDrive at 120-133 MHz.
-
-ROM files needed:
- revenge\1009af2_.bi0
- revenge\1009af2_.bi1
-
-
-Packard Bell PB520R (Robin LC) (1995)
-
-Pentium at 60-66 MHz, Pentium OverDrive at 120-133 MHz, 1-128MB RAM, built-in Cirrus
-Logic GD-5434.
-
-ROM files needed:
- pb520r/1009bc0r.bio
- pb520r/1009bc0r.bi1
- pb520r/gd5434.bin
-
-
-Packard Bell PB570 (Hillary) (1995)
-
-Pentium at 75-133 MHz, Pentium Overdrive at 125-200 MHz, 1-128MB RAM, built-in Cirrus
-Logic GD-5430.
-
-ROM files needed:
- pb570/1007by0r.bio
- pb570/1007by0r.bi1
- pb570/gd5430.bin
-
-
-PCem emulates the following graphics adapters :
-
-
-MDA (1981)
-80x25 monochrome text.
-
-
-CGA (1981)
-40x25 and 80x25 text, 320x200 in 4 colours, 620x200 in 2 colours. Supports composite
-output for ~16 colours.
-
-
-Hercules (1982)
-80x25 monochrome text, 720x348 in monochrome.
-
-
-Plantronics ColorPlus
-An enhanced CGA board, with support for 320x200x16 and 640x200x4.
-
-
-Wyse WY-700
-A CGA-compatible board, with support for a 1280x800 mode
-
-
-IBM EGA (1984)
-Text up to 80x43, graphics up to 640x350 in 16 colours.
-
-ROM files needed:
- ibm_6277356_ega_card_u44_27128.bin
-
-
-Hercules InColor
-An enhanced Hercules with a custom 720x350 16 colour mode.
-
-
-Unaccelerated (S)VGA cards :
-
-
-ATI Korean VGA
-ATI-28800 based. 512kb VRAM, supports up to 8-bit colour. Korean font support.
-
-ROM files needed:
- atikorvga.bin
- ati_ksc5601.rom
-
-
-ATI VGA Edge-16
-ATI-18800 based. 512kb VRAM, supports up to 8-bit colour.
-
-ROM files needed:
- vgaedge16.vbi
-
-
-ATI VGA Charger
-ATI-28800 based. 512kb VRAM, supports up to 8-bit colour.
-
-ROM files needed:
- bios.bin
-
-
-IBM VGA (1987)
-256kb VRAM, Text up to 80x50, graphics up to 320x200 in 256 colours or 640x480 in 16 colours.
-
-ROM files needed:
- ibm_vga.bin
-
-
-OAK OTI-037C
-256kb VRAM, supports up to 8-bit colour.
-
-ROM files needed:
- oti037\bios.bin
-
-
-OAK OTI-067
-256kb-512kb VRAM, supports up to 8-bit colour.
-
-ROM files needed:
- oti067\bios.bin
-
-
-Olivetti GO481 (Paradise PVGA1A)
-256kb VRAM, supports up to 8-bit colour.
-
-ROM files needed :
- oli_go481_lo.bin
- oli_go481_hi.bin
-
-
-Trident 8900D SVGA
-256kb-1MB VRAM, supports up to 24-bit colour.
-
-ROM files needed:
- trident.bin
-
-
-Trident TGUI9400CXi
-1-2MB VRAM, supports up to 24-bit colour.
-
-ROM files needed:
-9440.vbi
-
-
-Tseng ET4000AX SVGA
-1MB VRAM, supports up to 8-bit colour.
-
-ROM files needed:
- et4000.bin
-
-
-2D accelerated SVGA cards :
-
-ATI Graphics Pro Turbo
-Mach64GX based. 1-4MB VRAM.
-
-ROM files needed:
- mach64gx\bios.bin
-
-
-ATI Video Xpression
-Mach64VT2 based. 2-4MB VRAM. Has video acceleration.
-
-ROM files needed :
- atimach64vt2pci.bin
-
-
-Cirrus Logic GD-5429
-1-2MB VRAM.
-
-ROM files needed:
- 5429.vbi
-
-
-Cirrus Logic GD-5430
-1-2MB VRAM.
-
-ROM files needed:
- gd5430/pci.bin
-
-
-Cirrus Logic GD-5434
-2-4MB VRAM. Real chip also supports 1MB configurations, however this is not currently
-supported in PCem.
-
-ROM files needed:
- gd5434.bin
-
-
-Diamond Stealth 32 SVGA
-ET4000/W32p based. 1-2MB VRAM.
-
-ROM files needed:
- et4000w32.bin
-
-
-Number Nine 9FX
-S3 Trio64 based. 1-2MB VRAM.
-
-ROM files needed:
- s3_764.bin
-
-
-Paradise Bahamas 64
-S3 Vision864 based. 1-4MB VRAM.
-
-ROM files needed:
- bahamas64.bin
-
-
-Phoenix S3 Trio32
-S3 Trio32 based. 512kb-2MB VRAM.
-
-ROM files needed:
- 86c732p.bin
-
-
-Phoenix S3 Trio64
-S3 Trio64 based. 1MB-4MB VRAM.
-
-ROM files needed:
- 86c764x1.bin
-
-
-Trident TGUI9440
-Trident TGUI9440 based. 1-2MB VRAM.
-
-ROM files needed:
-9440.vbi
-
-
-
-3D accelerated SVGA cards :
-
-
-Diamond Stealth 3D 2000
-S3 ViRGE/325 based. 2-4MB VRAM.
-
-PCem emulates the ViRGE S3D engine in software. This works with most games I tried, but
-there may be some issues. The Direct3D drivers for the /325 are fairly poor (often showing
-as missing triangles), so use of the /DX instead is recommended.
-
-The streams processor (video overlay) is also emulated, however many features are missing.
-
-ROM files needed:
- s3virge.bin
-
-
-S3 ViRGE/DX
-S3 ViRGE/DX based. 2-4MB VRAM.
-
-The drivers that come with Windows are similar to those for the /325, however better ones
-do exist (try the 8-21-1997 version). With the correct drivers, many early Direct3D games
-work okay (if slowly).
-
-ROM files needed:
-86c375_1.bin
-
-
-3D only cards :
-
-3DFX Voodoo Graphics
-3D accelerator. Widely supported in late 90s games.
-
-PCem emulates this in software. The emulation is a lot faster than in v10 (thanks to a new
-dynamic recompiler) and should be capable of hitting Voodoo 1 performance on most machines
-when two render threads are used. As before, the emulated CPU is the bottleneck for most games.
-
-PCem can emulate 6 and 8 MB configurations, but defaults to 4 MB for compatibility. It can also
-emulate the screen filter present on the original card, though this does at present have a
-noticeable performance hit.
-
-Almost everything I've tried works okay, with a very few exceptions - Screamer 2 and Rally have
-serious issues.
-
-
-Obsidian SB50
-Voodoo Graphics with 2 TMUs. Drivers for this are a bit limited - the official drivers don't
-support 2 TMUs in Direct3D.
-
-
-Voodoo 2
-Improved Voodoo Graphics - higher clocks, 2 TMUs, triangle setup etc.
-
-PCem can emulate both 8 and 12 MB configurations. It can also emulate 6 and 10 MB configurations
-(with 2MB framebuffer memory), which were never sold into the PC market but do exist for arcade
-systems.
-
-
-Some models have fixed graphics adapters :
-
-Amstrad MegaPC
-Paradise 90C11. A development of the PVGA1, with 512kb VRAM. Can use external video card.
-
-Acer 386SX/25N
-Oak OTI-067. Another 512kb SVGA clone. Can use external video card.
-
-Amstrad PC1512
-CGA with a new mode (640x200x16).
-
-Amstrad PC1640
-Paradise EGA. Can use external video card.
-
-Amstrad PC2086/PC3086
-Paradise PVGA1. An early SVGA clone with 256kb VRAM. Can use external video card.
-
-Elonex PC-425X
-Trident TGUI9400CXi with 512kb VRAM.
-
-IBM PCjr
-CGA with various new modes - 160x200x16, 320x200x16, 640x200x4.
-
-IBM PS/1 Model 2011
-Stock VGA with 256kb VRAM.
-
-IBM PS/1 Model 2121
-Basic (and unknown) SVGA with 256kb VRAM.
-
-IBM PS/2 machines
-Stock VGA with 256kb VRAM.
-
-Olivetti M24
-CGA with double-res text modes and a 640x400 mode. I haven't seen a dump of the font
-ROM for this yet, so if one is not provided the MDA font will be used - which looks slightly odd
-as it is 14-line instead of 16-line.
-
-Packard Bell PB520R
-Cirrus Logic GD-5434. Can use external video card.
-
-Packard Bell PB570
-Cirrus Logic GD-5430. Can use external video card.
-
-Sinclair PC200
-CGA. Can use external video card.
-
-Tandy 1000
-Clone of PCjr video. Widely supported in 80s games.
-
-Tandy 1000 SL/2
-Improvement of Tandy 1000, with support for 640x200x16.
-
-Toshiba T-series
-CGA on built-in LCD or plasma display.
-
-
-
-PCem emulates the following sound devices :
-
-PC speaker
-The standard beeper on all PCs. Supports samples/RealSound.
-
-Tandy PSG
-The Texas Instruments chip in the PCjr and Tandy 1000. Supports 3 voices plus
-noise. I reused the emulator in B-em for this (slightly modified).
-PCem emulates the differences between the SN76496 (PCjr and Tandy 1000), and the NCR8496
-(currently assigned to the Tandy 1000HX). Maniac Mansion and Zak McKraken will only sound
-correct on the latter.
-
-Tandy PSSJ
-Used on the Tandy 1000SL/2, this clones the NCR8496, adding an addition frequency divider (did any
-software actually use this?) and an 8-bit DAC.
-
-PS/1 audio card
-An SN76496 clone plus an 8-bit DAC. The SN76496 isn't at the same address as PCjr/Tandy, so most
-software doesn't support it.
-
-Gameblaster
-The Creative Labs Gameblaster/Creative Music System, Creative's first sound card
-introduced in 1987. Has two Philips SAA1099, giving 12 voices of square waves plus 4 noise
-voices. In stereo!
-
-Adlib
-Has a Yamaha YM3812, giving 9 voices of 2 op FM, or 6 voices plus a rhythm section. PCem
-uses the DOSBox dbopl emulator.
-
-Adlib Gold
-OPL3 with YM318Z 12-bit digital section. Possibly some bugs (not a lot of software to test).
-The surround module is now emulated.
-
-Sound Blaster
-Several Sound Blasters are emulated :
- SB v1.0 - The original. Limited to 22khz, and no auto-init DMA (can cause crackles sometimes).
- SB v1.5 - Adds auto-init DMA
- SB v2.0 - Upped to 41khz
- SB Pro v1.0 - Stereo, with twin OPL2 chips.
- SB Pro v2.0 - Stereo, with OPL 3 chip
- SB 16 - 16 bit stereo
- SB AWE32 - SB 16 + wavetable MIDI. This requires a ROM dump from a real AWE32.
-All are set to Address 220, IRQ 7 and DMA 1 (and High DMA 5). IRQ and DMA can be changed for the
-SB16 & AWE32 in the drivers.
-The relevant SET line for autoexec.bat is
- SET BLASTER = A220 I7 D1 Tx - where Tx is T1 for SB v1.0, T3 for SB v2.0, T4 for SB Pro,
- and T6 for SB16.
-
-AWE32 requires a ROM dump called awe32.raw. AWE-DUMP is a utility which can get a dump from a real
-card. Most EMU8000 functionality should work, however filters are not correct and reverb/chorus
-effects are not currently emulated.
-
-Gravis Ultrasound
-32 voice sample playback. Port address is fixed to 240, IRQ and DMA can be changed from the drivers.
-Emulation is improved significantly over previous versions.
-
-Windows Sound System
-16-bit digital + OPL3. Note that this only emulates WSS itself, and should not be used with drivers
-from compatible boards with additional components (eg Turtle Beach Monte Carlo)
-
-Innovation SSI-2001
-SID6581. Emulated using resid-fp. Board is fixed to port 280.
-
-Ensoniq AudioPCI (ES1371) / Sound Blaster PCI 128
-Basic PCI sound card. Emulates Sound Blaster in software.
-
-
-PCem emulates the following hard drive controllers :
-
-[MFM] Fixed Disk Adapter (Xebec)
-MFM controller originally included in the IBM XT. This controller only supports HD types 0, 2, 13
-and 16.
-
-ROM files needed :
-ibm_xebec_62x0822_1985.bin
-
-
-[MFM] DTC 5150X
-8-bit MFM controller. To configure drive types, run DEBUG.EXE and enter 'g=c800:5'.
-
-ROM files needed :
-dtc_cxd21a.bin
-
-
-[MFM] AT Fixed Disk Adapter
-MFM controller originally included in the IBM AT. Supported by all AT-compatible BIOSes.
-
-
-[ESDI] Western Digital WD1007V-SE1
-16-bit ESDI controller.
-
-ROM files needed :
-62-000279-061.bin
-
-
-[ESDI] IBM ESDI Fixed Disk Controller
-MCA ESDI controller. Only supported on PS/2 models.
-
-ROM files needed :
-90x8969.bin
-90x8970.bin
-
-
-[IDE] Standard IDE
-Standard IDE controller. Supported by all AT-compatible BIOSes. Use this if in any doubt!
-
-
-[IDE] XTIDE
-8-bit IDE controller. The BIOS is available at :
-
-http://code.google.com/p/xtideuniversalbios/
-
-v2.0.0 beta 1 is the version I've mostly tested. v2.0.0 beta 3 is known to have some issues.
-
-ROM files needed :
-ide_xt.bin
-
-
-[IDE] XTIDE (AT)
-16-bit IDE controller.
-
-ROM files needed :
-ide_at.bin
-
-
-[IDE] XTIDE (PS/1)
-IDE controller for the PS/1 model 2033. For this machine you will need BIOS version v1.1.5. The
-PS/1 is a bit fussy with XTIDE, and I've found that it works best when the XTIDE configuration
-has 'Full Operating Mode' disabled.
-
-ROM files needed :
-ide_at_1_1_5.bin
-
-
-[SCSI] Longshine LCS-6821N
-8-bit SCSI controller.
-
-ROM files needed :
-Longshine LCS-6821N - BIOS version 1.04.bin
-
-
-[SCSI] Rancho RT1000B
-8-bit SCSI controller.
-
-ROM files needed :
-Rancho_RT1000_RTBios_version_8.10R.bin
-
-
-[SCSI] Trantor T130B
-8-bit SCSI controller.
-
-ROM files needed :
-trantor_t130b_bios_v2.14.bin
-
-
-[SCSI] Adaptec AHA-1542C
-16-bit SCSI controller.
-
-ROM files needed :
-adaptec_aha1542c_bios_534201-00.bin
-
-
-[SCSI] BusLogic BT-545S
-16-bit SCSI controller.
-
-ROM files needed :
-BusLogic_BT-545S_U15_27128_5002026-4.50.bin
-
-
-Other stuff emulated :
-
-Serial mouse
-A Microsoft compatible serial mouse on COM1. Compatible drivers are all over the place for this.
-
-M24 mouse
-I haven't seen a DOS mouse driver for this yet, but the regular scancode mode works, as does the
-Windows 1.x driver.
-
-PC1512 mouse
-The PC1512's perculiar quadrature mouse. You need Amstrad's actual driver for this one.
-
-PS/2 mouse
-A standard 2 button PS/2 mouse. As with serial, compatible drivers are common.
-
-Microsoft PS/2 Intellimouse
-A PS/2 mouse with mouse wheel.
-
-ATAPI CD-ROM
-Works with OAKCDROM.SYS, VDD-IDE.SYS, and the internal drivers of every OS I've tried.
-
-
-
-
-
-Software tested:
-
-CP/M-86 1.0
-
-PC-DOS 1.0
-MS-DOS 2.11
-MS-DOS 3.30
-PC-DOS 4.01
-MS-DOS 5.0
-PC-DOS 5.02
-MS-DOS 6.0
-MS-DOS 6.22
-
-Windows 1.03
-Windows/286 2.11
-Windows/386 2.11
-Windows 3.0
-Windows 3.1
-Windows for Workgroups 3.11
-Windows 95
-Windows 95 OSR2
-Windows 98
-Windows 98 SE
-Windows ME
-
-Windows NT 3.51
-Windows NT 4
-Windows 2000
-Windows XP
-
-OS/2 v1.0
-OS/2 v1.1
-OS/2 v1.2
-OS/2 v1.3
-OS/2 v2.1
-OS/2 Warp 3
-OS/2 Warp 4
-
-Corel Linux 1.2
-Red Hat Linux 7.1 (Seawolf)
-
-Solaris 2.4
-Solaris 2.5.1
-
-BeOS 5 Personal
-BeOS 5 Professional
-
-DESQview/X
-
-GEM Desktop 3.11
-
-After Dark 3.0
-Aldus PageMaker 5.0
-Ami Pro 3.0
-Borland C++ 3.1
-Cubasis v1.13
-Fasttracker 2.08
-Firefox 12.0
-Internet Explorer 5 (windows 3.x and 9x versions tested)
-Microsoft Basic 4.0
-Microsoft Office 95
-Microsoft Visual C++ 6.0 Standard Edition
-Microsoft Word 1.1
-Microsoft Word for Windows 1.1
-Microsoft Word for Windows 2.0c
-Microsoft Word 6.0
-Microsoft Works 2.0
-Microsoft Works for Windows 3.0
-Netscape Communicator 4.73
-Norton Utilities 8.0
-PC Paintbrush v1.05
-Photoshop v3.0.4
-Tantrakr
-
-Actua Soccer
-Age of Empires
-Aladdin
-All New World of Lemmings
-American McGee's Alice
-Area 51
-Arkanoid
-Ascendancy
-Battlezone
-Beyond Castle Wolfenstein
-Bio Menace (shareware)
-Blood 2
-Boppin'
-Brix (shareware)
-Bust-A-Move 2
-Caesar 3
-Cannon Fodder 2
-CART: Precision Racing
-Civilization II
-Clusterball
-Command and Conquer : Red Alert
-Commando
-Commandos: Behind Enemy Lines
-Commandos: Beyond the Call of Duty
-Conquest
-Corridor 7
-Curse of Monkey Island
-Dawn Patrol
-Desert Strike
-Dethkarz
-Deus Ex
-Discworld II
-Digger
-Dogz
-Doom (v1.2 registered)
-Doom II (v1.666)
-Double Dragon
-Down Under Dan
-Drakan : Order of the Flame
-Dreamweb
-Duke Nukem 3D (shareware)
-Dune
-Dune II
-Dungeon Keeper 2
-Earthworm Jim (DOS)
-Epic Pinball (v2.1 registered)
-Final Fantasy VII
-Forsaken
-Frogger
-G-Police
-Grand Theft Auto
-Hardwar
-Heartlight
-Heretic
-Heretic II
-Hitch-Hiker's Guide to the Galaxy
-Hocus Pocus (v1.1 shareware)
-House of the Dead 2
-Incoming
-Jazz Jackrabbit
-Jazz Jackrabbit 2
-Joe Montana Football
-Jumpman
-King's Quest
-King's Quest II
-Lemmings
-Lemmings 2 : The Tribes
-Little Big Adventure 2
-Lotus III
-Mageslayer
-Maniac Mansion
-Maniac Mansion (enhanced)
-Microsoft Arcade
-Monkey Island 2
-Monster Bash (shareware)
-Monster Truck Madness
-Mortal Kombat II
-Mortal Kombat Trilogy
-Necrodome
-Need for Speed II SE
-Nerf Arena Blast
-Network Q RAC Rally
-NFL Blitz
-NFL Blitz 2000
-Pax Corpus
-Pinball Fantasies
-Pinball Illusions
-Police Quest II
-Power Drive
-Prince of Persia
-Pro Pinball : Big Race USA
-Pro Pinball : The Web
-Pro Pinball : Timeshock
-Puyo Puyo Tsu
-Quake (v1.01 registered)
-Quake 2
-Quake III Arena
-Railroad Tycoon II
-Rampage World Tour
-Rayman
-Redline Racer (1998 US release)
-Revolution X
-Rollercoaster Tycoon
-Rollo and the Brush Bros
-Screamer
-Screamer 2
-Secret of Monkey Island
-SimCity 2000 (DOS)
-SimCity 2000 (OS/2)
-SimCity 3000 (Linux)
-Slipstream 5000
-Sonic R
-Space Strike
-Star Trek : Starfleet Command
-Star Trek : Voyager - Elite Force
-Stargunner
-Super Zaxxon
-Syndicate
-System Shock
-Take No Prisoners
-Terminal Velocity
-TFX
-The Humans
-The Lion King
-The Ultimate Doom (v1.9)
-Theme Hospital
-Theme Park (floppy version)
-Tomb Raider
-Tomb Raider II
-Tony Hawks Pro Skater 2
-Total Annihilation
-Transport Tycoon
-Transport Tycoon Deluxe
-Turok : Dinosaur Hunter
-Turrican II
-UFO : Enemy Unknown (v1.2)
-Unreal
-Unreal Tournament
-Wacky Wheels
-Warcraft II
-Wargasm
-Wetrix
-Wing Commander 3
-Wing Commander Privateer
-Wolfenstein 3D (v1.4 registered)
-Worms
-Worms United
-Worms 2
-X-Wing (floppy version)
-Zak McKracken
-Zone 66 (shareware)
-Zone Raiders
-
-Cascada - Cronologia
-Complex - Cyboman 2
-EMF - Verses
-Future Crew - Second Reality
-Gazebo - Cyboman!
-Hornet - Introjr
-Logic Design - Fashion
-Orange - X14
-Renaissance - Amnesia
-Skull - Putrefaction
-Tran - Ambience
-Tran - Luminati
-Tran - Timeless
-Triton - Crystal Dream
-Triton - Crystal Dream II
-Ultraforce - Coldcut
-Ultraforce - Vectdemo
-Witan - Witan House
-
-BeebInC v0.99f
-Fellow v0.33
-KGen98 v0.4b
-PaCifiST v0.45
-SNES9x v0.96
-vMac v1.9.1.1
-ZSNES v0.800
\ No newline at end of file
diff --git a/src/386.c b/src/386.c
index 48522c9..fc9cb3b 100644
--- a/src/386.c
+++ b/src/386.c
@@ -165,6 +165,8 @@ void exec386(int cycs)
// pclog("%i %02X\n", ins, ram[8]);
while (cycdiff < cycle_period)
{
+ int ins_cycles = cycles;
+
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
@@ -194,7 +196,7 @@ void exec386(int cycs)
flags_rebuild();
// pclog("Abort\n");
// if (CS == 0x228) pclog("Abort at %04X:%04X - %i %i %i\n",CS,pc,notpresent,nullseg,abrt);
- tempi = cpu_state.abrt;
+ tempi = cpu_state.abrt & ABRT_MASK;
cpu_state.abrt = 0;
x86_doabrt(tempi);
if (cpu_state.abrt)
@@ -212,9 +214,13 @@ void exec386(int cycs)
}
}
}
- cycdiff=oldcyc-cycles;
- if (trap)
+ if (cpu_state.smi_pending)
+ {
+ cpu_state.smi_pending = 0;
+ x86_smi_enter();
+ }
+ else if (trap)
{
flags_rebuild();
// oldpc=pc;
@@ -281,6 +287,11 @@ void exec386(int cycs)
ins++;
insc++;
+ ins_cycles -= cycles;
+ tsc += ins_cycles;
+
+ cycdiff=oldcyc-cycles;
+
if (timetolive)
{
timetolive--;
@@ -289,7 +300,6 @@ void exec386(int cycs)
}
}
- tsc += cycdiff;
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
timer_process();
}
diff --git a/src/386_common.c b/src/386_common.c
index df19e14..4d0a761 100644
--- a/src/386_common.c
+++ b/src/386_common.c
@@ -9,6 +9,9 @@ x86seg gdt, ldt, idt, tr;
uint32_t cr2, cr3, cr4;
uint32_t dr[8];
+uint16_t sysenter_cs;
+uint32_t sysenter_eip, sysenter_esp;
+
uint32_t use32;
int stack32;
int optype;
diff --git a/src/386_common.h b/src/386_common.h
index 80da16d..143984a 100644
--- a/src/386_common.h
+++ b/src/386_common.h
@@ -19,7 +19,10 @@ int checkio(int port);
if (cpu_state.abrt) return 1; \
if (tempi) \
{ \
- x86gpf(NULL,0); \
+ if (cpu_state.eflags & VM_FLAG) \
+ x86gpf_expected(NULL,0); \
+ else \
+ x86gpf(NULL,0); \
return 1; \
} \
}
diff --git a/src/386_dynarec.c b/src/386_dynarec.c
index eaa2041..ec56e57 100644
--- a/src/386_dynarec.c
+++ b/src/386_dynarec.c
@@ -1,6 +1,9 @@
#include
#include
#include
+#if defined(__APPLE__) && defined(__aarch64__)
+#include
+#endif
#include "ibm.h"
#include "x86.h"
#include "x86_ops.h"
@@ -212,6 +215,8 @@ static void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int
}
prefetch_prefixes = 0;
+ if (prefetch_bytes > 16)
+ prefetch_bytes = 16;
}
static void prefetch_flush()
@@ -236,11 +241,344 @@ static void prefetch_flush()
#define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG))
//#define CACHE_ON() 0
-static int cycles_main = 0;
+int cpu_end_block_after_ins = 0;
+
+
+static inline void exec_interpreter(void)
+{
+ cpu_block_end = 0;
+ x86_was_reset = 0;
+// if (output) pclog("Interpret block at %04x:%04x %04x %04x %04x %04x %04x %04x %04x\n", CS, pc, AX, BX, CX, DX, SI, DI, SP);
+ while (!cpu_block_end)
+ {
+ cpu_state.oldpc = cpu_state.pc;
+ cpu_state.op32 = use32;
+
+ cpu_state.ea_seg = &cpu_state.seg_ds;
+ cpu_state.ssegs = 0;
+
+ fetchdat = fastreadl(cs + cpu_state.pc);
+
+ if (!cpu_state.abrt)
+ {
+ uint8_t opcode = fetchdat & 0xFF;
+ fetchdat >>= 8;
+ trap = cpu_state.flags & T_FLAG;
+
+// if (output == 3)
+// pclog("int %04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0x8f13f], ram[0x8f13e], ram[0x8f141], ram[0x8f140]);
+
+ cpu_state.pc++;
+ x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
+ }
+
+ if (((cs + cpu_state.pc) >> 12) != pccache)
+ CPU_BLOCK_END();
+
+ if (cpu_state.abrt)
+ CPU_BLOCK_END();
+ if (cpu_state.smi_pending)
+ CPU_BLOCK_END();
+ if (trap)
+ CPU_BLOCK_END();
+ if (nmi && nmi_enable && nmi_mask)
+ CPU_BLOCK_END();
+ if (cpu_end_block_after_ins)
+ {
+ cpu_end_block_after_ins--;
+ if (!cpu_end_block_after_ins)
+ CPU_BLOCK_END();
+ }
+
+ ins++;
+ insc++;
+ }
+
+ if (trap)
+ {
+ trap = 0;
+ cpu_state.oldpc = cpu_state.pc;
+ x86_int(1);
+ }
+
+ cpu_end_block_after_ins = 0;
+}
+
+static inline void exec_recompiler(void)
+{
+ uint32_t phys_addr = get_phys(cs+cpu_state.pc);
+ int hash = HASH(phys_addr);
+ codeblock_t *block = &codeblock[codeblock_hash[hash]];
+ int valid_block = 0;
+
+ if (!cpu_state.abrt)
+ {
+ page_t *page = &pages[phys_addr >> 12];
+
+ /*Block must match current CS, PC, code segment size,
+ and physical address. The physical address check will
+ also catch any page faults at this stage*/
+ valid_block = (block->pc == cs + cpu_state.pc) && (block->_cs == cs) &&
+ (block->phys == phys_addr) && !((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
+ ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK));
+ if (!valid_block)
+ {
+ uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
+ int byte_offset = (phys_addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
+ uint64_t byte_mask = 1ull << (PAGE_BYTE_MASK_MASK & 0x3f);
+
+ if ((page->code_present_mask & mask) || (page->byte_code_present_mask[byte_offset] & byte_mask))
+ {
+ /*Walk page tree to see if we find the correct block*/
+ codeblock_t *new_block = codeblock_tree_find(phys_addr, cs);
+ if (new_block)
+ {
+ valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) &&
+ (new_block->phys == phys_addr) && !((new_block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
+ ((new_block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK));
+ if (valid_block)
+ {
+ block = new_block;
+ codeblock_hash[hash] = get_block_nr(block);
+ }
+ }
+ }
+ }
+
+ if (valid_block && (block->page_mask & *block->dirty_mask))
+ {
+ codegen_check_flush(page, page->dirty_mask, phys_addr);
+ if (block->pc == BLOCK_PC_INVALID)
+ valid_block = 0;
+ else if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
+ block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
+ }
+ if (valid_block && block->page_mask2)
+ {
+ /*We don't want the second page to cause a page
+ fault at this stage - that would break any
+ code crossing a page boundary where the first
+ page is present but the second isn't. Instead
+ allow the first page to be interpreted and for
+ the page fault to occur when the page boundary
+ is actually crossed.*/
+ uint32_t phys_addr_2 = get_phys_noabrt(block->pc + ((block->flags & CODEBLOCK_BYTE_MASK) ? 0x40 : 0x400));
+ page_t *page_2 = &pages[phys_addr_2 >> 12];
+ if ((block->phys_2 ^ phys_addr_2) & ~0xfff)
+ valid_block = 0;
+ else if (block->page_mask2 & *block->dirty_mask2)
+ {
+ codegen_check_flush(page_2, page_2->dirty_mask, phys_addr_2);
+ if (block->pc == BLOCK_PC_INVALID)
+ valid_block = 0;
+ else if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
+ block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
+ }
+ }
+ if (valid_block && (block->flags & CODEBLOCK_IN_DIRTY_LIST))
+ {
+ block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
+ if (block->flags & CODEBLOCK_BYTE_MASK)
+ block->flags |= CODEBLOCK_NO_IMMEDIATES;
+ else
+ block->flags |= CODEBLOCK_BYTE_MASK;
+ }
+ if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7))
+ {
+ /*FPU top-of-stack does not match the value this block was compiled
+ with, re-compile using dynamic top-of-stack*/
+ block->flags &= ~(CODEBLOCK_STATIC_TOP | CODEBLOCK_WAS_RECOMPILED);
+ }
+ }
+
+ if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED))
+ {
+ void (*code)() = (void *)&block->data[BLOCK_START];
+
+// if (output) pclog("Run block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%08x %04x %08x %08x %016llx %08x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, get_phys(cs+pc), block->phys, block->page_mask, block->endpc);
+
+ inrecomp=1;
+ code();
+ inrecomp=0;
+
+ cpu_recomp_blocks++;
+ }
+ else if (valid_block && !cpu_state.abrt)
+ {
+ uint32_t start_pc = cs+cpu_state.pc;
+ const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000;
+
+ cpu_block_end = 0;
+ x86_was_reset = 0;
+
+ cpu_new_blocks++;
+
+#if defined(__APPLE__) && defined(__aarch64__)
+ pthread_jit_write_protect_np(0);
+#endif
+ codegen_block_start_recompile(block);
+ codegen_in_recompile = 1;
+
+// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]);
+ while (!cpu_block_end)
+ {
+ cpu_state.oldpc = cpu_state.pc;
+ cpu_state.op32 = use32;
+
+ cpu_state.ea_seg = &cpu_state.seg_ds;
+ cpu_state.ssegs = 0;
+
+ fetchdat = fastreadl(cs + cpu_state.pc);
+
+ if (!cpu_state.abrt)
+ {
+ uint8_t opcode = fetchdat & 0xFF;
+ fetchdat >>= 8;
+
+// if (output == 3)
+// pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache);
+
+ cpu_state.pc++;
+
+ codegen_generate_call(opcode, x86_opcodes[(opcode | cpu_state.op32) & 0x3ff], fetchdat, cpu_state.pc, cpu_state.pc-1);
+
+ x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
+
+ if (x86_was_reset)
+ break;
+ }
+
+ /*Cap source code at 4000 bytes per block; this
+ will prevent any block from spanning more than
+ 2 pages. In practice this limit will never be
+ hit, as host block size is only 2kB*/
+ if (((cs+cpu_state.pc) - start_pc) >= max_block_size)
+ CPU_BLOCK_END();
+ if (cpu_state.flags & T_FLAG)
+ CPU_BLOCK_END();
+ if (cpu_state.smi_pending)
+ CPU_BLOCK_END();
+ if (nmi && nmi_enable && nmi_mask)
+ CPU_BLOCK_END();
+
+ if (cpu_end_block_after_ins)
+ {
+ cpu_end_block_after_ins--;
+ if (!cpu_end_block_after_ins)
+ CPU_BLOCK_END();
+ }
+
+ if (cpu_state.abrt)
+ {
+ if (!(cpu_state.abrt & ABRT_EXPECTED))
+ codegen_block_remove();
+ CPU_BLOCK_END();
+ }
+
+ ins++;
+ insc++;
+ }
+ cpu_end_block_after_ins = 0;
+
+ if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !x86_was_reset)
+ codegen_block_end_recompile(block);
+
+ if (x86_was_reset)
+ codegen_reset();
+
+ codegen_in_recompile = 0;
+#if defined(__APPLE__) && defined(__aarch64__)
+ pthread_jit_write_protect_np(1);
+#endif
+ }
+ else if (!cpu_state.abrt)
+ {
+ /*Mark block but do not recompile*/
+ uint32_t start_pc = cs+cpu_state.pc;
+ const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000;
+
+ cpu_block_end = 0;
+ x86_was_reset = 0;
+
+ codegen_block_init(phys_addr);
+
+// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]);
+ while (!cpu_block_end)
+ {
+ cpu_state.oldpc = cpu_state.pc;
+ cpu_state.op32 = use32;
+
+ cpu_state.ea_seg = &cpu_state.seg_ds;
+ cpu_state.ssegs = 0;
+
+ codegen_endpc = (cs + cpu_state.pc) + 8;
+ fetchdat = fastreadl(cs + cpu_state.pc);
+
+ if (!cpu_state.abrt)
+ {
+ uint8_t opcode = fetchdat & 0xFF;
+ fetchdat >>= 8;
+
+// if (output == 3)
+// pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache);
+
+ cpu_state.pc++;
+
+ x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
+
+ if (x86_was_reset)
+ break;
+ }
+
+ /*Cap source code at 4000 bytes per block; this
+ will prevent any block from spanning more than
+ 2 pages. In practice this limit will never be
+ hit, as host block size is only 2kB*/
+ if (((cs+cpu_state.pc) - start_pc) >= max_block_size)
+ CPU_BLOCK_END();
+ if (cpu_state.flags & T_FLAG)
+ CPU_BLOCK_END();
+ if (cpu_state.smi_pending)
+ CPU_BLOCK_END();
+ if (nmi && nmi_enable && nmi_mask)
+ CPU_BLOCK_END();
+
+ if (cpu_end_block_after_ins)
+ {
+ cpu_end_block_after_ins--;
+ if (!cpu_end_block_after_ins)
+ CPU_BLOCK_END();
+ }
+
+ if (cpu_state.abrt)
+ {
+ if (!(cpu_state.abrt & ABRT_EXPECTED))
+ codegen_block_remove();
+ CPU_BLOCK_END();
+ }
+
+ ins++;
+ insc++;
+ }
+ cpu_end_block_after_ins = 0;
+
+// if (!cpu_state.abrt && !x86_was_reset)
+ if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !x86_was_reset)
+ codegen_block_end();
+
+ if (x86_was_reset)
+ codegen_reset();
+ }
+ else
+ cpu_state.oldpc = cpu_state.pc;
+
+}
+
+
+int cycles_main = 0;
void exec386_dynarec(int cycs)
{
uint8_t temp;
- uint32_t addr;
int tempi;
int cycdiff;
int oldcyc;
@@ -259,303 +597,14 @@ void exec386_dynarec(int cycs)
oldcyc=cycles;
// if (output && CACHE_ON()) pclog("Block %04x:%04x %04x:%08x\n", CS, pc, SS,ESP);
if (!CACHE_ON()) /*Interpret block*/
- {
- cpu_block_end = 0;
- x86_was_reset = 0;
-// if (output) pclog("Interpret block at %04x:%04x %04x %04x %04x %04x %04x %04x %04x\n", CS, pc, AX, BX, CX, DX, SI, DI, SP);
- while (!cpu_block_end)
- {
- cpu_state.oldpc = cpu_state.pc;
- cpu_state.op32 = use32;
-
- cpu_state.ea_seg = &cpu_state.seg_ds;
- cpu_state.ssegs = 0;
-
- fetchdat = fastreadl(cs + cpu_state.pc);
-
- if (!cpu_state.abrt)
- {
- uint8_t opcode = fetchdat & 0xFF;
- fetchdat >>= 8;
- trap = cpu_state.flags & T_FLAG;
-
-// if (output == 3)
-// pclog("int %04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0x8f13f], ram[0x8f13e], ram[0x8f141], ram[0x8f140]);
-
- cpu_state.pc++;
- x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
- }
-
- if (((cs + cpu_state.pc) >> 12) != pccache)
- CPU_BLOCK_END();
-
- if (cpu_state.abrt)
- CPU_BLOCK_END();
- if (trap)
- CPU_BLOCK_END();
- if (nmi && nmi_enable && nmi_mask)
- CPU_BLOCK_END();
-
- ins++;
- insc++;
- }
- }
+ exec_interpreter();
else
- {
- uint32_t phys_addr = get_phys(cs+cpu_state.pc);
- int hash = HASH(phys_addr);
- codeblock_t *block = &codeblock[codeblock_hash[hash]];
- int valid_block = 0;
-
- if (!cpu_state.abrt)
- {
- page_t *page = &pages[phys_addr >> 12];
-
- /*Block must match current CS, PC, code segment size,
- and physical address. The physical address check will
- also catch any page faults at this stage*/
- valid_block = (block->pc == cs + cpu_state.pc) && (block->_cs == cs) &&
- (block->phys == phys_addr) && !((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
- ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK));
- if (!valid_block)
- {
- uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
- int byte_offset = (phys_addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
- uint64_t byte_mask = 1ull << (PAGE_BYTE_MASK_MASK & 0x3f);
-
- if ((page->code_present_mask & mask) || (page->byte_code_present_mask[byte_offset] & byte_mask))
- {
- /*Walk page tree to see if we find the correct block*/
- codeblock_t *new_block = codeblock_tree_find(phys_addr, cs);
- if (new_block)
- {
- valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) &&
- (new_block->phys == phys_addr) && !((new_block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
- ((new_block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK));
- if (valid_block)
- {
- block = new_block;
- codeblock_hash[hash] = get_block_nr(block);
- }
- }
- }
- }
-
- if (valid_block && (block->page_mask & *block->dirty_mask))
- {
- codegen_check_flush(page, page->dirty_mask, phys_addr);
- if (block->pc == BLOCK_PC_INVALID)
- valid_block = 0;
- else if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
- block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
- }
- if (valid_block && block->page_mask2)
- {
- /*We don't want the second page to cause a page
- fault at this stage - that would break any
- code crossing a page boundary where the first
- page is present but the second isn't. Instead
- allow the first page to be interpreted and for
- the page fault to occur when the page boundary
- is actually crossed.*/
- uint32_t phys_addr_2 = get_phys_noabrt(block->pc + ((block->flags & CODEBLOCK_BYTE_MASK) ? 0x40 : 0x400));
- page_t *page_2 = &pages[phys_addr_2 >> 12];
- if ((block->phys_2 ^ phys_addr_2) & ~0xfff)
- valid_block = 0;
- else if (block->page_mask2 & *block->dirty_mask2)
- {
- codegen_check_flush(page_2, page_2->dirty_mask, phys_addr_2);
- if (block->pc == BLOCK_PC_INVALID)
- valid_block = 0;
- else if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
- block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
- }
- }
- if (valid_block && (block->flags & CODEBLOCK_IN_DIRTY_LIST))
- {
- block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
- if (block->flags & CODEBLOCK_BYTE_MASK)
- block->flags |= CODEBLOCK_NO_IMMEDIATES;
- else
- block->flags |= CODEBLOCK_BYTE_MASK;
- }
- if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7))
- {
- /*FPU top-of-stack does not match the value this block was compiled
- with, re-compile using dynamic top-of-stack*/
- block->flags &= ~(CODEBLOCK_STATIC_TOP | CODEBLOCK_WAS_RECOMPILED);
- }
- }
-
- if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED))
- {
- void (*code)() = (void *)&block->data[BLOCK_START];
-
-// if (output) pclog("Run block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%08x %04x %08x %08x %016llx %08x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, get_phys(cs+pc), block->phys, block->page_mask, block->endpc);
-
- inrecomp=1;
- code();
- inrecomp=0;
-
- cpu_recomp_blocks++;
- }
- else if (valid_block && !cpu_state.abrt)
- {
- uint32_t start_pc = cs+cpu_state.pc;
- const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000;
-
- cpu_block_end = 0;
- x86_was_reset = 0;
-
- cpu_new_blocks++;
-
- codegen_block_start_recompile(block);
- codegen_in_recompile = 1;
-
-// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]);
- while (!cpu_block_end)
- {
- cpu_state.oldpc = cpu_state.pc;
- cpu_state.op32 = use32;
-
- cpu_state.ea_seg = &cpu_state.seg_ds;
- cpu_state.ssegs = 0;
-
- fetchdat = fastreadl(cs + cpu_state.pc);
-
- if (!cpu_state.abrt)
- {
- uint8_t opcode = fetchdat & 0xFF;
- fetchdat >>= 8;
-
- trap = cpu_state.flags & T_FLAG;
-
-// if (output == 3)
-// pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache);
-
- cpu_state.pc++;
-
- codegen_generate_call(opcode, x86_opcodes[(opcode | cpu_state.op32) & 0x3ff], fetchdat, cpu_state.pc, cpu_state.pc-1);
-
- x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
-
- if (x86_was_reset)
- break;
- }
-
- /*Cap source code at 4000 bytes per block; this
- will prevent any block from spanning more than
- 2 pages. In practice this limit will never be
- hit, as host block size is only 2kB*/
- if (((cs+cpu_state.pc) - start_pc) >= max_block_size)
- CPU_BLOCK_END();
-
- if (trap)
- CPU_BLOCK_END();
-
- if (nmi && nmi_enable && nmi_mask)
- CPU_BLOCK_END();
-
- if (cpu_state.abrt)
- {
- codegen_block_remove();
- CPU_BLOCK_END();
- }
-
- ins++;
- insc++;
- }
-
- if (!cpu_state.abrt && !x86_was_reset)
- codegen_block_end_recompile(block);
-
- if (x86_was_reset)
- codegen_reset();
-
- codegen_in_recompile = 0;
- }
- else if (!cpu_state.abrt)
- {
- /*Mark block but do not recompile*/
- uint32_t start_pc = cs+cpu_state.pc;
- const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000;
-
- cpu_block_end = 0;
- x86_was_reset = 0;
-
- codegen_block_init(phys_addr);
-
-// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]);
- while (!cpu_block_end)
- {
- cpu_state.oldpc = cpu_state.pc;
- cpu_state.op32 = use32;
-
- cpu_state.ea_seg = &cpu_state.seg_ds;
- cpu_state.ssegs = 0;
-
- codegen_endpc = (cs + cpu_state.pc) + 8;
- fetchdat = fastreadl(cs + cpu_state.pc);
-
- if (!cpu_state.abrt)
- {
- uint8_t opcode = fetchdat & 0xFF;
- fetchdat >>= 8;
-
- trap = cpu_state.flags & T_FLAG;
-
-// if (output == 3)
-// pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache);
-
- cpu_state.pc++;
-
- x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
-
- if (x86_was_reset)
- break;
- }
-
- /*Cap source code at 4000 bytes per block; this
- will prevent any block from spanning more than
- 2 pages. In practice this limit will never be
- hit, as host block size is only 2kB*/
- if (((cs+cpu_state.pc) - start_pc) >= max_block_size)
- CPU_BLOCK_END();
-
- if (trap)
- CPU_BLOCK_END();
-
- if (nmi && nmi_enable && nmi_mask)
- CPU_BLOCK_END();
-
- if (cpu_state.abrt)
- {
- codegen_block_remove();
- CPU_BLOCK_END();
- }
-
- ins++;
- insc++;
- }
-
- if (!cpu_state.abrt && !x86_was_reset)
- codegen_block_end();
-
- if (x86_was_reset)
- codegen_reset();
- }
- else
- cpu_state.oldpc = cpu_state.pc;
-
- }
-
- cycdiff=oldcyc-cycles;
- tsc += cycdiff;
+ exec_recompiler();
if (cpu_state.abrt)
{
flags_rebuild();
- tempi = cpu_state.abrt;
+ tempi = cpu_state.abrt & ABRT_MASK;
cpu_state.abrt = 0;
x86_doabrt(tempi);
if (cpu_state.abrt)
@@ -574,26 +623,10 @@ void exec386_dynarec(int cycs)
}
}
- if (trap)
+ if (cpu_state.smi_pending)
{
- trap = 0;
- flags_rebuild();
- if (msw&1)
- {
- pmodeint(1,0);
- }
- else
- {
- writememw(ss,(SP-2)&0xFFFF,cpu_state.flags);
- writememw(ss,(SP-4)&0xFFFF,CS);
- writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
- SP-=6;
- addr = (1 << 2) + idt.base;
- cpu_state.flags &= ~I_FLAG;
- cpu_state.flags &= ~T_FLAG;
- cpu_state.pc=readmemw(0,addr);
- loadcs(readmemw(0,addr+2));
- }
+ cpu_state.smi_pending = 0;
+ x86_smi_enter();
}
else if (nmi && nmi_enable && nmi_mask)
{
@@ -612,27 +645,14 @@ void exec386_dynarec(int cycs)
temp=picinterrupt();
if (temp!=0xFF)
{
+ cpu_state.oldpc = cpu_state.pc;
+ x86_int(temp);
// pclog("IRQ %02X %04X:%04X %04X:%04X\n", temp, SS, SP, CS, pc);
- CPU_BLOCK_END();
- flags_rebuild();
- if (msw&1)
- {
- pmodeint(temp,0);
- }
- else
- {
- writememw(ss,(SP-2)&0xFFFF,cpu_state.flags);
- writememw(ss,(SP-4)&0xFFFF,CS);
- writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
- SP-=6;
- addr=temp<<2;
- cpu_state.flags &= ~I_FLAG;
- cpu_state.flags &= ~T_FLAG;
- cpu_state.pc=readmemw(0,addr);
- loadcs(readmemw(0,addr+2));
- }
}
}
+
+ cycdiff=oldcyc-cycles;
+ tsc += cycdiff;
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
diff --git a/src/386_ops.h b/src/386_ops.h
index 2ad1789..d59132a 100644
--- a/src/386_ops.h
+++ b/src/386_ops.h
@@ -119,6 +119,7 @@ static int ILLEGAL(uint32_t fetchdat)
#include "x86_ops_bit.h"
#include "x86_ops_bitscan.h"
#include "x86_ops_call.h"
+#include "x86_ops_cyrix.h"
#include "x86_ops_flag.h"
#include "x86_ops_fpu.h"
#include "x86_ops_inc_dec.h"
@@ -280,7 +281,7 @@ OpFn OP_TABLE(386_0f)[1024] =
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -302,7 +303,7 @@ OpFn OP_TABLE(386_0f)[1024] =
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -324,7 +325,7 @@ OpFn OP_TABLE(386_0f)[1024] =
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -346,7 +347,7 @@ OpFn OP_TABLE(386_0f)[1024] =
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -371,7 +372,7 @@ OpFn OP_TABLE(winchip_0f)[1024] =
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -381,7 +382,7 @@ OpFn OP_TABLE(winchip_0f)[1024] =
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
-/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -393,7 +394,7 @@ OpFn OP_TABLE(winchip_0f)[1024] =
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -403,7 +404,7 @@ OpFn OP_TABLE(winchip_0f)[1024] =
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
-/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -415,7 +416,7 @@ OpFn OP_TABLE(winchip_0f)[1024] =
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -425,7 +426,7 @@ OpFn OP_TABLE(winchip_0f)[1024] =
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
-/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -437,7 +438,7 @@ OpFn OP_TABLE(winchip_0f)[1024] =
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -447,7 +448,7 @@ OpFn OP_TABLE(winchip_0f)[1024] =
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
-/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -462,7 +463,7 @@ OpFn OP_TABLE(winchip2_0f)[1024] =
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -472,7 +473,7 @@ OpFn OP_TABLE(winchip2_0f)[1024] =
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
-/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -484,7 +485,7 @@ OpFn OP_TABLE(winchip2_0f)[1024] =
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -494,7 +495,7 @@ OpFn OP_TABLE(winchip2_0f)[1024] =
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
-/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -506,7 +507,7 @@ OpFn OP_TABLE(winchip2_0f)[1024] =
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a32, opFEMMS, op3DNOW_a32,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -516,7 +517,7 @@ OpFn OP_TABLE(winchip2_0f)[1024] =
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
-/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -528,7 +529,7 @@ OpFn OP_TABLE(winchip2_0f)[1024] =
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a32, opFEMMS, op3DNOW_a32,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -538,7 +539,7 @@ OpFn OP_TABLE(winchip2_0f)[1024] =
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
-/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -563,7 +564,7 @@ OpFn OP_TABLE(pentium_0f)[1024] =
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
-/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -585,7 +586,7 @@ OpFn OP_TABLE(pentium_0f)[1024] =
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
-/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -607,7 +608,7 @@ OpFn OP_TABLE(pentium_0f)[1024] =
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
-/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -629,7 +630,7 @@ OpFn OP_TABLE(pentium_0f)[1024] =
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
-/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -638,7 +639,98 @@ OpFn OP_TABLE(pentium_0f)[1024] =
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
};
-OpFn OP_TABLE(pentiummmx_0f)[1024] =
+OpFn OP_TABLE(c6x86_0f)[1024] =
+{
+ /*16-bit data, 16-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL,
+
+/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
+/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
+/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
+
+/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+ /*32-bit data, 16-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL,
+
+/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
+/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
+/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
+
+/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+ /*16-bit data, 32-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opSMINT, ILLEGAL,
+
+/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
+/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
+/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
+
+/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+ /*32-bit data, 32-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opSMINT, ILLEGAL,
+
+/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
+/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
+/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
+
+/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+};
+
+OpFn OP_TABLE(pentiummmx_0f)[1024] =
{
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
@@ -654,7 +746,7 @@ OpFn OP_TABLE(pentiummmx_0f)[1024] =
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
-/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -676,7 +768,7 @@ OpFn OP_TABLE(pentiummmx_0f)[1024] =
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
-/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -698,7 +790,7 @@ OpFn OP_TABLE(pentiummmx_0f)[1024] =
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
-/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -720,7 +812,7 @@ OpFn OP_TABLE(pentiummmx_0f)[1024] =
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
-/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -736,16 +828,16 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] =
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ opCMOVO_w_a16, opCMOVNO_w_a16, opCMOVB_w_a16, opCMOVNB_w_a16, opCMOVE_w_a16, opCMOVNE_w_a16, opCMOVBE_w_a16, opCMOVNBE_w_a16,opCMOVS_w_a16, opCMOVNS_w_a16, opCMOVP_w_a16, opCMOVNP_w_a16, opCMOVL_w_a16, opCMOVNL_w_a16, opCMOVLE_w_a16, opCMOVNLE_w_a16,
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16,
-/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16,
+/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a16_cx,opMOVQ_mm_q_a16,
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
-/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -758,16 +850,16 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] =
/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ opCMOVO_l_a16, opCMOVNO_l_a16, opCMOVB_l_a16, opCMOVNB_l_a16, opCMOVE_l_a16, opCMOVNE_l_a16, opCMOVBE_l_a16, opCMOVNBE_l_a16,opCMOVS_l_a16, opCMOVNS_l_a16, opCMOVP_l_a16, opCMOVNP_l_a16, opCMOVL_l_a16, opCMOVNL_l_a16, opCMOVLE_l_a16, opCMOVNLE_l_a16,
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16,
-/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16,
+/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a16_cx,opMOVQ_mm_q_a16,
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
-/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -780,16 +872,16 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] =
/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ opCMOVO_w_a32, opCMOVNO_w_a32, opCMOVB_w_a32, opCMOVNB_w_a32, opCMOVE_w_a32, opCMOVNE_w_a32, opCMOVBE_w_a32, opCMOVNBE_w_a32,opCMOVS_w_a32, opCMOVNS_w_a32, opCMOVP_w_a32, opCMOVNP_w_a32, opCMOVL_w_a32, opCMOVNL_w_a32, opCMOVLE_w_a32, opCMOVNLE_w_a32,
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32,
-/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32,
+/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opMOVD_mm_l_a32_cx,opMOVQ_mm_q_a32,
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
-/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -802,16 +894,16 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] =
/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ opCMOVO_l_a32, opCMOVNO_l_a32, opCMOVB_l_a32, opCMOVNB_l_a32, opCMOVE_l_a32, opCMOVNE_l_a32, opCMOVBE_l_a32, opCMOVNBE_l_a32,opCMOVS_l_a32, opCMOVNS_l_a32, opCMOVP_l_a32, opCMOVNP_l_a32, opCMOVL_l_a32, opCMOVNL_l_a32, opCMOVLE_l_a32, opCMOVNLE_l_a32,
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32,
-/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32,
+/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a32_cx,opMOVQ_mm_q_a32,
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
-/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
@@ -820,7 +912,189 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] =
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
};
-OpFn OP_TABLE(286)[1024] =
+OpFn OP_TABLE(pentiumpro_0f)[1024] =
+{
+ /*16-bit data, 16-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ opCMOVO_w_a16, opCMOVNO_w_a16, opCMOVB_w_a16, opCMOVNB_w_a16, opCMOVE_w_a16, opCMOVNE_w_a16, opCMOVBE_w_a16, opCMOVNBE_w_a16,opCMOVS_w_a16, opCMOVNS_w_a16, opCMOVP_w_a16, opCMOVNP_w_a16, opCMOVL_w_a16, opCMOVNL_w_a16, opCMOVLE_w_a16, opCMOVNLE_w_a16,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
+/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
+/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
+
+/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+ /*32-bit data, 16-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ opCMOVO_l_a16, opCMOVNO_l_a16, opCMOVB_l_a16, opCMOVNB_l_a16, opCMOVE_l_a16, opCMOVNE_l_a16, opCMOVBE_l_a16, opCMOVNBE_l_a16,opCMOVS_l_a16, opCMOVNS_l_a16, opCMOVP_l_a16, opCMOVNP_l_a16, opCMOVL_l_a16, opCMOVNL_l_a16, opCMOVLE_l_a16, opCMOVNLE_l_a16,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
+/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
+/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
+
+/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+ /*16-bit data, 32-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ opCMOVO_w_a32, opCMOVNO_w_a32, opCMOVB_w_a32, opCMOVNB_w_a32, opCMOVE_w_a32, opCMOVNE_w_a32, opCMOVBE_w_a32, opCMOVNBE_w_a32,opCMOVS_w_a32, opCMOVNS_w_a32, opCMOVP_w_a32, opCMOVNP_w_a32, opCMOVL_w_a32, opCMOVNL_w_a32, opCMOVLE_w_a32, opCMOVNLE_w_a32,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
+/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
+/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
+
+/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+ /*32-bit data, 32-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ opCMOVO_l_a32, opCMOVNO_l_a32, opCMOVB_l_a32, opCMOVNB_l_a32, opCMOVE_l_a32, opCMOVNE_l_a32, opCMOVBE_l_a32, opCMOVNBE_l_a32,opCMOVS_l_a32, opCMOVNS_l_a32, opCMOVP_l_a32, opCMOVNP_l_a32, opCMOVL_l_a32, opCMOVNL_l_a32, opCMOVLE_l_a32, opCMOVNLE_l_a32,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
+/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
+/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
+
+/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+};
+
+OpFn OP_TABLE(pentium2_0f)[1024] =
+{
+ /*16-bit data, 16-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ opCMOVO_w_a16, opCMOVNO_w_a16, opCMOVB_w_a16, opCMOVNB_w_a16, opCMOVE_w_a16, opCMOVNE_w_a16, opCMOVBE_w_a16, opCMOVNBE_w_a16,opCMOVS_w_a16, opCMOVNS_w_a16, opCMOVP_w_a16, opCMOVNP_w_a16, opCMOVL_w_a16, opCMOVNL_w_a16, opCMOVLE_w_a16, opCMOVNLE_w_a16,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16,
+/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16,
+
+/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
+/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
+/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
+
+/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16,
+/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16,
+/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL,
+
+ /*32-bit data, 16-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ opCMOVO_l_a16, opCMOVNO_l_a16, opCMOVB_l_a16, opCMOVNB_l_a16, opCMOVE_l_a16, opCMOVNE_l_a16, opCMOVBE_l_a16, opCMOVNBE_l_a16,opCMOVS_l_a16, opCMOVNS_l_a16, opCMOVP_l_a16, opCMOVNP_l_a16, opCMOVL_l_a16, opCMOVNL_l_a16, opCMOVLE_l_a16, opCMOVNLE_l_a16,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16,
+/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16,
+
+/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
+/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
+/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
+
+/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16,
+/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16,
+/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL,
+
+ /*16-bit data, 32-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ opCMOVO_w_a32, opCMOVNO_w_a32, opCMOVB_w_a32, opCMOVNB_w_a32, opCMOVE_w_a32, opCMOVNE_w_a32, opCMOVBE_w_a32, opCMOVNBE_w_a32,opCMOVS_w_a32, opCMOVNS_w_a32, opCMOVP_w_a32, opCMOVNP_w_a32, opCMOVL_w_a32, opCMOVNL_w_a32, opCMOVLE_w_a32, opCMOVNLE_w_a32,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32,
+/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32,
+
+/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
+/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
+/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
+
+/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
+/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
+/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
+
+ /*32-bit data, 32-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ opCMOVO_l_a32, opCMOVNO_l_a32, opCMOVB_l_a32, opCMOVNB_l_a32, opCMOVE_l_a32, opCMOVNE_l_a32, opCMOVBE_l_a32, opCMOVNBE_l_a32,opCMOVS_l_a32, opCMOVNS_l_a32, opCMOVP_l_a32, opCMOVNP_l_a32, opCMOVL_l_a32, opCMOVNL_l_a32, opCMOVLE_l_a32, opCMOVNLE_l_a32,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32,
+/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32,
+
+/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
+/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
+/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
+
+/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
+/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
+/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
+};
+
+OpFn OP_TABLE(286)[1024] =
{
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
diff --git a/src/8087.h b/src/8087.h
new file mode 100644
index 0000000..6e5401a
--- /dev/null
+++ b/src/8087.h
@@ -0,0 +1,98 @@
+/*This file is a series of macros to get the 386+ based x87 emulation working with
+ the 808x emulation*/
+#define X8087
+#define OP_TABLE(name) ops_808x_ ## name
+
+#define CLOCK_CYCLES(c) cycles -= (c)
+#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
+
+#define fetch_ea_16(fetchdat)
+#define fetch_ea_32(fetchdat)
+#define SEG_CHECK_READ(seg)
+#define SEG_CHECK_WRITE(seg)
+#define CHECK_WRITE(seg, addr_lo, addr_hi)
+#define PREFETCH_RUN(timing, bytes, rmdat, a, b, c, d, e)
+
+static uint32_t readmeml(uint32_t seg, uint32_t addr)
+{
+ return readmemw(seg, addr) | (readmemw(seg, addr+2) << 16);
+}
+static uint64_t readmemq(uint32_t seg, uint32_t addr)
+{
+ return (uint64_t)readmemw(seg, addr) | ((uint64_t)readmemw(seg, addr+2) << 16) |
+ ((uint64_t)readmemw(seg, addr+4) << 32) |
+ ((uint64_t)readmemw(seg, addr+6) << 48);
+}
+
+static void writememb_8087(uint32_t seg, uint32_t addr, uint8_t val)
+{
+ writememb(seg+addr, val);
+}
+static void writememl(uint32_t seg, uint32_t addr, uint32_t val)
+{
+ writememw(seg, addr, val & 0xffff);
+ writememw(seg, addr+2, (val >> 16) & 0xffff);
+}
+static void writememq(uint32_t seg, uint32_t addr, uint64_t val)
+{
+ writememw(seg, addr, val & 0xffff);
+ writememw(seg, addr+2, (val >> 16) & 0xffff);
+ writememw(seg, addr+4, (val >> 32) & 0xffff);
+ writememw(seg, addr+6, (val >> 48) & 0xffff);
+}
+
+static inline uint32_t geteal()
+{
+ if (cpu_mod == 3)
+ fatal("geteal cpu_mod==3\n");
+ return readmeml(easeg, cpu_state.eaaddr);
+}
+static inline uint64_t geteaq()
+{
+ if (cpu_mod == 3)
+ fatal("geteaq cpu_mod==3\n");
+ return readmemq(easeg, cpu_state.eaaddr);
+}
+static inline void seteal(uint32_t val)
+{
+ if (cpu_mod == 3)
+ fatal("seteal cpu_mod==3\n");
+ else
+ writememl(easeg, cpu_state.eaaddr, val);
+}
+static inline void seteaq(uint64_t val)
+{
+ if (cpu_mod == 3)
+ fatal("seteaq cpu_mod==3\n");
+ else
+ writememq(easeg, cpu_state.eaaddr, val);
+}
+
+#define flags_rebuild()
+
+#define CF_SET() (cpu_state.flags & C_FLAG)
+#define NF_SET() (cpu_state.flags & N_FLAG)
+#define PF_SET() (cpu_state.flags & P_FLAG)
+#define VF_SET() (cpu_state.flags & V_FLAG)
+#define ZF_SET() (cpu_state.flags & Z_FLAG)
+
+#define cond_O ( VF_SET())
+#define cond_NO (!VF_SET())
+#define cond_B ( CF_SET())
+#define cond_NB (!CF_SET())
+#define cond_E ( ZF_SET())
+#define cond_NE (!ZF_SET())
+#define cond_BE ( CF_SET() || ZF_SET())
+#define cond_NBE (!CF_SET() && !ZF_SET())
+#define cond_S ( NF_SET())
+#define cond_NS (!NF_SET())
+#define cond_P ( PF_SET())
+#define cond_NP (!PF_SET())
+#define cond_L (((NF_SET()) ? 1 : 0) != ((VF_SET()) ? 1 : 0))
+#define cond_NL (((NF_SET()) ? 1 : 0) == ((VF_SET()) ? 1 : 0))
+#define cond_LE (((NF_SET()) ? 1 : 0) != ((VF_SET()) ? 1 : 0) || (ZF_SET()))
+#define cond_NLE (((NF_SET()) ? 1 : 0) == ((VF_SET()) ? 1 : 0) && (!ZF_SET()))
+
+#define writememb writememb_8087
+#include "x87_ops.h"
+#undef writememb
diff --git a/src/808x.c b/src/808x.c
index 3ac3dae..825d9f9 100644
--- a/src/808x.c
+++ b/src/808x.c
@@ -523,7 +523,7 @@ void dumpregs()
putc(readmembl(c+0x80000000),f);
}
fclose(f);
- pclog("Dumping done\n");
+ pclog("Dumping done\n");
/* f=fopen("rram6.dmp","wb");
for (c=0;c<0x1000000;c++) putc(readmemb(c+0xBF000000),f);
fclose(f);*/
@@ -583,6 +583,7 @@ void dumpregs()
{
printf("386 in %s mode stack in %s mode\n",(use32)?"32-bit":"16-bit",(stack32)?"32-bit":"16-bit");
printf("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n",cr0,cr2,cr3, cr4);
+ pclog("SMBASE=%08x\n", cpu_state.smbase);
}
printf("Entries in readlookup : %i writelookup : %i\n",readlnum,writelnum);
for (c=0;c<1024*1024;c++)
@@ -641,6 +642,7 @@ void resetx86()
x86seg_reset();
codegen_reset();
x86_was_reset = 1;
+ cpu_state.smbase = 0x30000;
}
void softresetx86()
@@ -677,11 +679,19 @@ void softresetx86()
//rammask=0xFFFFFFFF;
cpu_state.flags=2;
idt.base = 0;
- idt.limit = is386 ? 0x03FF : 0xFFFF;
- EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0;
+ if (is386)
+ {
+ idt.limit = 0x03FF;
+ EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0;
+ }
+ else
+ {
+ idt.limit = 0xFFFF;
+ }
x86seg_reset();
flushmmucache();
x86_was_reset = 1;
+ FETCHCLEAR();
}
static void setznp8(uint8_t val)
@@ -1104,6 +1114,8 @@ static void rep(int fv)
static int inhlt=0;
static int skipnextprint=0;
+#include "8087.h"
+
void execx86(int cycs)
{
uint8_t temp,temp2;
@@ -2945,10 +2957,78 @@ void execx86(int cycs)
AL=readmemb(ds+addr);
cycles-=11;
break;
- case 0xD9: case 0xDA: case 0xDB: case 0xDD: /*ESCAPE*/
- case 0xDC: case 0xDE: case 0xDF: case 0xD8:
+
+ case 0xd8:
fetchea();
- geteab();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_d8_a16[rmdat >> 3](rmdat);
+ cpu_state.pc = save_pc;
+ }
+ break;
+ case 0xd9:
+ fetchea();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_d9_a16[rmdat](rmdat);
+ cpu_state.pc = save_pc;
+ }
+ break;
+ case 0xda:
+ fetchea();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_da_a16[rmdat](rmdat);
+ cpu_state.pc = save_pc;
+ }
+ break;
+ case 0xdb:
+ fetchea();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_db_a16[rmdat](rmdat);
+ cpu_state.pc = save_pc;
+ }
+ break;
+ case 0xdc:
+ fetchea();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_dc_a16[rmdat >> 3](rmdat);
+ cpu_state.pc = save_pc;
+ }
+ break;
+ case 0xdd:
+ fetchea();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_dd_a16[rmdat](rmdat);
+ cpu_state.pc = save_pc;
+ }
+ break;
+ case 0xde:
+ fetchea();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_de_a16[rmdat](rmdat);
+ cpu_state.pc = save_pc;
+ }
+ break;
+ case 0xdf:
+ fetchea();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_df_a16[rmdat](rmdat);
+ cpu_state.pc = save_pc;
+ }
break;
case 0xE0: /*LOOPNE*/
@@ -3494,14 +3574,6 @@ void execx86(int cycs)
// if (instime) printf("%i %i %i %i\n",cycdiff,cycles,memcycs,fetchclocks);
FETCHADD(((cycdiff-cycles)-memcycs)-fetchclocks);
if ((cycdiff-cycles) minivhd/$(am__dirstamp)
+minivhd/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) minivhd/$(DEPDIR)
+ @: > minivhd/$(DEPDIR)/$(am__dirstamp)
+minivhd/pcem-cwalk.$(OBJEXT): minivhd/$(am__dirstamp) \
+ minivhd/$(DEPDIR)/$(am__dirstamp)
+minivhd/pcem-libxml2_encoding.$(OBJEXT): minivhd/$(am__dirstamp) \
+ minivhd/$(DEPDIR)/$(am__dirstamp)
+minivhd/pcem-minivhd_convert.$(OBJEXT): minivhd/$(am__dirstamp) \
+ minivhd/$(DEPDIR)/$(am__dirstamp)
+minivhd/pcem-minivhd_create.$(OBJEXT): minivhd/$(am__dirstamp) \
+ minivhd/$(DEPDIR)/$(am__dirstamp)
+minivhd/pcem-minivhd_io.$(OBJEXT): minivhd/$(am__dirstamp) \
+ minivhd/$(DEPDIR)/$(am__dirstamp)
+minivhd/pcem-minivhd_manage.$(OBJEXT): minivhd/$(am__dirstamp) \
+ minivhd/$(DEPDIR)/$(am__dirstamp)
+minivhd/pcem-minivhd_struct_rw.$(OBJEXT): minivhd/$(am__dirstamp) \
+ minivhd/$(DEPDIR)/$(am__dirstamp)
+minivhd/pcem-minivhd_util.$(OBJEXT): minivhd/$(am__dirstamp) \
+ minivhd/$(DEPDIR)/$(am__dirstamp)
slirp/$(am__dirstamp):
@$(MKDIR_P) slirp
@: > slirp/$(am__dirstamp)
@@ -1015,6 +1230,7 @@ pcem$(EXEEXT): $(pcem_OBJECTS) $(pcem_DEPENDENCIES) $(EXTRA_pcem_DEPENDENCIES)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
-rm -f dosbox/*.$(OBJEXT)
+ -rm -f minivhd/*.$(OBJEXT)
-rm -f resid-fp/*.$(OBJEXT)
-rm -f slirp/*.$(OBJEXT)
@@ -1022,13 +1238,18 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-386.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-386_common.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-386_dynarec.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-386_dynarec_ops.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-808x.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-82091aa.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-acc2036.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-acc2168.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-acc3221.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-acer386sx.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ali1429.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-amstrad.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cassette.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cbm_io.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cdrom-image.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cdrom-ioctl-dummy.Po@am__quote@ # am--include-marker
@@ -1038,24 +1259,62 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cdrom-null.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cmd640.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_accumulate.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_allocator.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_arm.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_arm64.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_arm64_imm.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_arm64_ops.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_arm64_uops.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_arm_ops.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_arm_uops.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_x86-64.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_x86-64_ops.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_x86-64_ops_sse.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_x86-64_uops.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_x86.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_x86_ops.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_x86_ops_fpu.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_x86_ops_sse.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_backend_x86_uops.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_block.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ir.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_3dnow.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_arith.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_branch.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_fpu_arith.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_fpu_constant.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_fpu_loadstore.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_fpu_misc.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_helpers.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_jump.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_logic.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_misc.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_mmx_arith.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_mmx_cmp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_mmx_loadstore.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_mmx_logic.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_mmx_pack.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_mmx_shift.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_mov.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_shift.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_ops_stack.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_reg.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_486.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_686.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_common.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_cyrixiii.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_k6.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_p6.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_pentium.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_winchip.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-codegen_timing_winchip2.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-compaq.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-config.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cpu.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cpu_tables.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-cs8230.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-dells200.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-disc.Po@am__quote@ # am--include-marker
@@ -1064,8 +1323,10 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-disc_sector.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-dma.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-esdi_at.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-f82c710_upc.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdc.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdc37c665.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdc37c93x.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdd.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-fdi2raw.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-gameport.Po@am__quote@ # am--include-marker
@@ -1074,10 +1335,14 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-hdd_file.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-headland.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-i430fx.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-i430hx.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-i430lx.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-i430vx.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-i440bx.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-i440fx.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ide.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ide_atapi.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ide_sff8038i.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-intel.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-intel_flash.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-io.Po@am__quote@ # am--include-marker
@@ -1108,6 +1373,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mouse_msystems.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mouse_ps2.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mouse_serial.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-mvp3.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ne2000.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-neat.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-nethandler.Po@am__quote@ # am--include-marker
@@ -1119,24 +1385,29 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-paths.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pc.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pc87306.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pc87307.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pci.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pic.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-piix.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-piix_pm.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pit.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ppi.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ps1.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ps2.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ps2_mca.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-ps2_nvr.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-pzx.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-rom.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-rtc.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-rtc_tc8521.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scamp.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scat.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_53c400.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_aha1540.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_cd.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_hd.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_ibm.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-scsi_zip.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-serial.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sio.Po@am__quote@ # am--include-marker
@@ -1147,6 +1418,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_adlib.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_adlibgold.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_audiopci.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_azt2316a.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_cms.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_dbopl.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_emu8k.Po@am__quote@ # am--include-marker
@@ -1165,6 +1437,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_wss.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sound_ym7128.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-soundopenal.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-sst39sf010.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-superxt.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-t1000.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-t3100e.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-tandy_eeprom.Po@am__quote@ # am--include-marker
@@ -1181,15 +1455,19 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_cl5429.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_colorplus.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_compaq_cga.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ddc.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ega.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_et4000.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_et4000w32.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_genius.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_hercules.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ht216.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_icd2061.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ics2595.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_im1024.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_incolor.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_mda.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_mga.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_olivetti_m24.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_oti037.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_oti067.Po@am__quote@ # am--include-marker
@@ -1198,10 +1476,12 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_pc1640.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_pc200.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_pcjr.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_pgc.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_ps1_svga.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_s3.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_s3_virge.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_sdac_ramdac.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_sigma.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_stg_ramdac.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_svga.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_svga_render.Po@am__quote@ # am--include-marker
@@ -1215,8 +1495,22 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_unk_ramdac.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_vga.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_voodoo.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_voodoo_banshee.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_voodoo_banshee_blitter.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_voodoo_blitter.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_voodoo_display.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_voodoo_fb.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_voodoo_fifo.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_voodoo_reg.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_voodoo_render.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_voodoo_setup.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_voodoo_texture.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vid_wy700.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-video.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vl82c480.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-vt82c586b.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-w83877tf.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-w83977tf.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wd76c10.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-app.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-common.Po@am__quote@ # am--include-marker
@@ -1248,12 +1542,21 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-wx-utils.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-x86seg.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-x87.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-x87_timings.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-xi8088.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcem-xtide.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@dosbox/$(DEPDIR)/pcem-cdrom_image.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@dosbox/$(DEPDIR)/pcem-dbopl.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@dosbox/$(DEPDIR)/pcem-nukedopl.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@dosbox/$(DEPDIR)/pcem-vid_cga_comp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@minivhd/$(DEPDIR)/pcem-cwalk.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@minivhd/$(DEPDIR)/pcem-libxml2_encoding.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@minivhd/$(DEPDIR)/pcem-minivhd_convert.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@minivhd/$(DEPDIR)/pcem-minivhd_create.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@minivhd/$(DEPDIR)/pcem-minivhd_io.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@minivhd/$(DEPDIR)/pcem-minivhd_manage.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@minivhd/$(DEPDIR)/pcem-minivhd_struct_rw.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@minivhd/$(DEPDIR)/pcem-minivhd_util.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-convolve-sse.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-convolve.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@resid-fp/$(DEPDIR)/pcem-envelope.Po@am__quote@ # am--include-marker
@@ -1327,6 +1630,20 @@ pcem-386.obj: 386.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-386.obj `if test -f '386.c'; then $(CYGPATH_W) '386.c'; else $(CYGPATH_W) '$(srcdir)/386.c'; fi`
+pcem-386_common.o: 386_common.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-386_common.o -MD -MP -MF $(DEPDIR)/pcem-386_common.Tpo -c -o pcem-386_common.o `test -f '386_common.c' || echo '$(srcdir)/'`386_common.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-386_common.Tpo $(DEPDIR)/pcem-386_common.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='386_common.c' object='pcem-386_common.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-386_common.o `test -f '386_common.c' || echo '$(srcdir)/'`386_common.c
+
+pcem-386_common.obj: 386_common.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-386_common.obj -MD -MP -MF $(DEPDIR)/pcem-386_common.Tpo -c -o pcem-386_common.obj `if test -f '386_common.c'; then $(CYGPATH_W) '386_common.c'; else $(CYGPATH_W) '$(srcdir)/386_common.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-386_common.Tpo $(DEPDIR)/pcem-386_common.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='386_common.c' object='pcem-386_common.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-386_common.obj `if test -f '386_common.c'; then $(CYGPATH_W) '386_common.c'; else $(CYGPATH_W) '$(srcdir)/386_common.c'; fi`
+
pcem-386_dynarec.o: 386_dynarec.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-386_dynarec.o -MD -MP -MF $(DEPDIR)/pcem-386_dynarec.Tpo -c -o pcem-386_dynarec.o `test -f '386_dynarec.c' || echo '$(srcdir)/'`386_dynarec.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-386_dynarec.Tpo $(DEPDIR)/pcem-386_dynarec.Po
@@ -1369,6 +1686,20 @@ pcem-808x.obj: 808x.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-808x.obj `if test -f '808x.c'; then $(CYGPATH_W) '808x.c'; else $(CYGPATH_W) '$(srcdir)/808x.c'; fi`
+pcem-82091aa.o: 82091aa.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-82091aa.o -MD -MP -MF $(DEPDIR)/pcem-82091aa.Tpo -c -o pcem-82091aa.o `test -f '82091aa.c' || echo '$(srcdir)/'`82091aa.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-82091aa.Tpo $(DEPDIR)/pcem-82091aa.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='82091aa.c' object='pcem-82091aa.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-82091aa.o `test -f '82091aa.c' || echo '$(srcdir)/'`82091aa.c
+
+pcem-82091aa.obj: 82091aa.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-82091aa.obj -MD -MP -MF $(DEPDIR)/pcem-82091aa.Tpo -c -o pcem-82091aa.obj `if test -f '82091aa.c'; then $(CYGPATH_W) '82091aa.c'; else $(CYGPATH_W) '$(srcdir)/82091aa.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-82091aa.Tpo $(DEPDIR)/pcem-82091aa.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='82091aa.c' object='pcem-82091aa.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-82091aa.obj `if test -f '82091aa.c'; then $(CYGPATH_W) '82091aa.c'; else $(CYGPATH_W) '$(srcdir)/82091aa.c'; fi`
+
pcem-acc2036.o: acc2036.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-acc2036.o -MD -MP -MF $(DEPDIR)/pcem-acc2036.Tpo -c -o pcem-acc2036.o `test -f 'acc2036.c' || echo '$(srcdir)/'`acc2036.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-acc2036.Tpo $(DEPDIR)/pcem-acc2036.Po
@@ -1383,6 +1714,34 @@ pcem-acc2036.obj: acc2036.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-acc2036.obj `if test -f 'acc2036.c'; then $(CYGPATH_W) 'acc2036.c'; else $(CYGPATH_W) '$(srcdir)/acc2036.c'; fi`
+pcem-acc2168.o: acc2168.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-acc2168.o -MD -MP -MF $(DEPDIR)/pcem-acc2168.Tpo -c -o pcem-acc2168.o `test -f 'acc2168.c' || echo '$(srcdir)/'`acc2168.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-acc2168.Tpo $(DEPDIR)/pcem-acc2168.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acc2168.c' object='pcem-acc2168.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-acc2168.o `test -f 'acc2168.c' || echo '$(srcdir)/'`acc2168.c
+
+pcem-acc2168.obj: acc2168.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-acc2168.obj -MD -MP -MF $(DEPDIR)/pcem-acc2168.Tpo -c -o pcem-acc2168.obj `if test -f 'acc2168.c'; then $(CYGPATH_W) 'acc2168.c'; else $(CYGPATH_W) '$(srcdir)/acc2168.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-acc2168.Tpo $(DEPDIR)/pcem-acc2168.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acc2168.c' object='pcem-acc2168.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-acc2168.obj `if test -f 'acc2168.c'; then $(CYGPATH_W) 'acc2168.c'; else $(CYGPATH_W) '$(srcdir)/acc2168.c'; fi`
+
+pcem-acc3221.o: acc3221.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-acc3221.o -MD -MP -MF $(DEPDIR)/pcem-acc3221.Tpo -c -o pcem-acc3221.o `test -f 'acc3221.c' || echo '$(srcdir)/'`acc3221.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-acc3221.Tpo $(DEPDIR)/pcem-acc3221.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acc3221.c' object='pcem-acc3221.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-acc3221.o `test -f 'acc3221.c' || echo '$(srcdir)/'`acc3221.c
+
+pcem-acc3221.obj: acc3221.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-acc3221.obj -MD -MP -MF $(DEPDIR)/pcem-acc3221.Tpo -c -o pcem-acc3221.obj `if test -f 'acc3221.c'; then $(CYGPATH_W) 'acc3221.c'; else $(CYGPATH_W) '$(srcdir)/acc3221.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-acc3221.Tpo $(DEPDIR)/pcem-acc3221.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acc3221.c' object='pcem-acc3221.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-acc3221.obj `if test -f 'acc3221.c'; then $(CYGPATH_W) 'acc3221.c'; else $(CYGPATH_W) '$(srcdir)/acc3221.c'; fi`
+
pcem-acer386sx.o: acer386sx.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-acer386sx.o -MD -MP -MF $(DEPDIR)/pcem-acer386sx.Tpo -c -o pcem-acer386sx.o `test -f 'acer386sx.c' || echo '$(srcdir)/'`acer386sx.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-acer386sx.Tpo $(DEPDIR)/pcem-acer386sx.Po
@@ -1425,6 +1784,20 @@ pcem-amstrad.obj: amstrad.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-amstrad.obj `if test -f 'amstrad.c'; then $(CYGPATH_W) 'amstrad.c'; else $(CYGPATH_W) '$(srcdir)/amstrad.c'; fi`
+pcem-cassette.o: cassette.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-cassette.o -MD -MP -MF $(DEPDIR)/pcem-cassette.Tpo -c -o pcem-cassette.o `test -f 'cassette.c' || echo '$(srcdir)/'`cassette.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-cassette.Tpo $(DEPDIR)/pcem-cassette.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cassette.c' object='pcem-cassette.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-cassette.o `test -f 'cassette.c' || echo '$(srcdir)/'`cassette.c
+
+pcem-cassette.obj: cassette.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-cassette.obj -MD -MP -MF $(DEPDIR)/pcem-cassette.Tpo -c -o pcem-cassette.obj `if test -f 'cassette.c'; then $(CYGPATH_W) 'cassette.c'; else $(CYGPATH_W) '$(srcdir)/cassette.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-cassette.Tpo $(DEPDIR)/pcem-cassette.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cassette.c' object='pcem-cassette.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-cassette.obj `if test -f 'cassette.c'; then $(CYGPATH_W) 'cassette.c'; else $(CYGPATH_W) '$(srcdir)/cassette.c'; fi`
+
pcem-cbm_io.o: cbm_io.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-cbm_io.o -MD -MP -MF $(DEPDIR)/pcem-cbm_io.Tpo -c -o pcem-cbm_io.o `test -f 'cbm_io.c' || echo '$(srcdir)/'`cbm_io.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-cbm_io.Tpo $(DEPDIR)/pcem-cbm_io.Po
@@ -1481,19 +1854,47 @@ pcem-codegen.obj: codegen.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen.obj `if test -f 'codegen.c'; then $(CYGPATH_W) 'codegen.c'; else $(CYGPATH_W) '$(srcdir)/codegen.c'; fi`
-pcem-codegen_backend.o: codegen_backend.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend.Tpo -c -o pcem-codegen_backend.o `test -f 'codegen_backend.c' || echo '$(srcdir)/'`codegen_backend.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend.Tpo $(DEPDIR)/pcem-codegen_backend.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend.c' object='pcem-codegen_backend.o' libtool=no @AMDEPBACKSLASH@
+pcem-codegen_accumulate.o: codegen_accumulate.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_accumulate.o -MD -MP -MF $(DEPDIR)/pcem-codegen_accumulate.Tpo -c -o pcem-codegen_accumulate.o `test -f 'codegen_accumulate.c' || echo '$(srcdir)/'`codegen_accumulate.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_accumulate.Tpo $(DEPDIR)/pcem-codegen_accumulate.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_accumulate.c' object='pcem-codegen_accumulate.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend.o `test -f 'codegen_backend.c' || echo '$(srcdir)/'`codegen_backend.c
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_accumulate.o `test -f 'codegen_accumulate.c' || echo '$(srcdir)/'`codegen_accumulate.c
-pcem-codegen_backend.obj: codegen_backend.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend.Tpo -c -o pcem-codegen_backend.obj `if test -f 'codegen_backend.c'; then $(CYGPATH_W) 'codegen_backend.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend.c'; fi`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend.Tpo $(DEPDIR)/pcem-codegen_backend.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend.c' object='pcem-codegen_backend.obj' libtool=no @AMDEPBACKSLASH@
+pcem-codegen_accumulate.obj: codegen_accumulate.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_accumulate.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_accumulate.Tpo -c -o pcem-codegen_accumulate.obj `if test -f 'codegen_accumulate.c'; then $(CYGPATH_W) 'codegen_accumulate.c'; else $(CYGPATH_W) '$(srcdir)/codegen_accumulate.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_accumulate.Tpo $(DEPDIR)/pcem-codegen_accumulate.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_accumulate.c' object='pcem-codegen_accumulate.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend.obj `if test -f 'codegen_backend.c'; then $(CYGPATH_W) 'codegen_backend.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend.c'; fi`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_accumulate.obj `if test -f 'codegen_accumulate.c'; then $(CYGPATH_W) 'codegen_accumulate.c'; else $(CYGPATH_W) '$(srcdir)/codegen_accumulate.c'; fi`
+
+pcem-codegen_allocator.o: codegen_allocator.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_allocator.o -MD -MP -MF $(DEPDIR)/pcem-codegen_allocator.Tpo -c -o pcem-codegen_allocator.o `test -f 'codegen_allocator.c' || echo '$(srcdir)/'`codegen_allocator.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_allocator.Tpo $(DEPDIR)/pcem-codegen_allocator.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_allocator.c' object='pcem-codegen_allocator.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_allocator.o `test -f 'codegen_allocator.c' || echo '$(srcdir)/'`codegen_allocator.c
+
+pcem-codegen_allocator.obj: codegen_allocator.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_allocator.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_allocator.Tpo -c -o pcem-codegen_allocator.obj `if test -f 'codegen_allocator.c'; then $(CYGPATH_W) 'codegen_allocator.c'; else $(CYGPATH_W) '$(srcdir)/codegen_allocator.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_allocator.Tpo $(DEPDIR)/pcem-codegen_allocator.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_allocator.c' object='pcem-codegen_allocator.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_allocator.obj `if test -f 'codegen_allocator.c'; then $(CYGPATH_W) 'codegen_allocator.c'; else $(CYGPATH_W) '$(srcdir)/codegen_allocator.c'; fi`
+
+pcem-codegen_block.o: codegen_block.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_block.o -MD -MP -MF $(DEPDIR)/pcem-codegen_block.Tpo -c -o pcem-codegen_block.o `test -f 'codegen_block.c' || echo '$(srcdir)/'`codegen_block.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_block.Tpo $(DEPDIR)/pcem-codegen_block.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_block.c' object='pcem-codegen_block.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_block.o `test -f 'codegen_block.c' || echo '$(srcdir)/'`codegen_block.c
+
+pcem-codegen_block.obj: codegen_block.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_block.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_block.Tpo -c -o pcem-codegen_block.obj `if test -f 'codegen_block.c'; then $(CYGPATH_W) 'codegen_block.c'; else $(CYGPATH_W) '$(srcdir)/codegen_block.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_block.Tpo $(DEPDIR)/pcem-codegen_block.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_block.c' object='pcem-codegen_block.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_block.obj `if test -f 'codegen_block.c'; then $(CYGPATH_W) 'codegen_block.c'; else $(CYGPATH_W) '$(srcdir)/codegen_block.c'; fi`
pcem-codegen_ir.o: codegen_ir.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ir.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ir.Tpo -c -o pcem-codegen_ir.o `test -f 'codegen_ir.c' || echo '$(srcdir)/'`codegen_ir.c
@@ -1509,6 +1910,314 @@ pcem-codegen_ir.obj: codegen_ir.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ir.obj `if test -f 'codegen_ir.c'; then $(CYGPATH_W) 'codegen_ir.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ir.c'; fi`
+pcem-codegen_ops.o: codegen_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops.Tpo -c -o pcem-codegen_ops.o `test -f 'codegen_ops.c' || echo '$(srcdir)/'`codegen_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops.Tpo $(DEPDIR)/pcem-codegen_ops.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops.c' object='pcem-codegen_ops.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops.o `test -f 'codegen_ops.c' || echo '$(srcdir)/'`codegen_ops.c
+
+pcem-codegen_ops.obj: codegen_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops.Tpo -c -o pcem-codegen_ops.obj `if test -f 'codegen_ops.c'; then $(CYGPATH_W) 'codegen_ops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops.Tpo $(DEPDIR)/pcem-codegen_ops.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops.c' object='pcem-codegen_ops.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops.obj `if test -f 'codegen_ops.c'; then $(CYGPATH_W) 'codegen_ops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops.c'; fi`
+
+pcem-codegen_ops_3dnow.o: codegen_ops_3dnow.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_3dnow.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_3dnow.Tpo -c -o pcem-codegen_ops_3dnow.o `test -f 'codegen_ops_3dnow.c' || echo '$(srcdir)/'`codegen_ops_3dnow.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_3dnow.Tpo $(DEPDIR)/pcem-codegen_ops_3dnow.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_3dnow.c' object='pcem-codegen_ops_3dnow.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_3dnow.o `test -f 'codegen_ops_3dnow.c' || echo '$(srcdir)/'`codegen_ops_3dnow.c
+
+pcem-codegen_ops_3dnow.obj: codegen_ops_3dnow.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_3dnow.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_3dnow.Tpo -c -o pcem-codegen_ops_3dnow.obj `if test -f 'codegen_ops_3dnow.c'; then $(CYGPATH_W) 'codegen_ops_3dnow.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_3dnow.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_3dnow.Tpo $(DEPDIR)/pcem-codegen_ops_3dnow.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_3dnow.c' object='pcem-codegen_ops_3dnow.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_3dnow.obj `if test -f 'codegen_ops_3dnow.c'; then $(CYGPATH_W) 'codegen_ops_3dnow.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_3dnow.c'; fi`
+
+pcem-codegen_ops_arith.o: codegen_ops_arith.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_arith.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_arith.Tpo -c -o pcem-codegen_ops_arith.o `test -f 'codegen_ops_arith.c' || echo '$(srcdir)/'`codegen_ops_arith.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_arith.Tpo $(DEPDIR)/pcem-codegen_ops_arith.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_arith.c' object='pcem-codegen_ops_arith.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_arith.o `test -f 'codegen_ops_arith.c' || echo '$(srcdir)/'`codegen_ops_arith.c
+
+pcem-codegen_ops_arith.obj: codegen_ops_arith.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_arith.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_arith.Tpo -c -o pcem-codegen_ops_arith.obj `if test -f 'codegen_ops_arith.c'; then $(CYGPATH_W) 'codegen_ops_arith.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_arith.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_arith.Tpo $(DEPDIR)/pcem-codegen_ops_arith.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_arith.c' object='pcem-codegen_ops_arith.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_arith.obj `if test -f 'codegen_ops_arith.c'; then $(CYGPATH_W) 'codegen_ops_arith.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_arith.c'; fi`
+
+pcem-codegen_ops_branch.o: codegen_ops_branch.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_branch.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_branch.Tpo -c -o pcem-codegen_ops_branch.o `test -f 'codegen_ops_branch.c' || echo '$(srcdir)/'`codegen_ops_branch.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_branch.Tpo $(DEPDIR)/pcem-codegen_ops_branch.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_branch.c' object='pcem-codegen_ops_branch.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_branch.o `test -f 'codegen_ops_branch.c' || echo '$(srcdir)/'`codegen_ops_branch.c
+
+pcem-codegen_ops_branch.obj: codegen_ops_branch.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_branch.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_branch.Tpo -c -o pcem-codegen_ops_branch.obj `if test -f 'codegen_ops_branch.c'; then $(CYGPATH_W) 'codegen_ops_branch.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_branch.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_branch.Tpo $(DEPDIR)/pcem-codegen_ops_branch.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_branch.c' object='pcem-codegen_ops_branch.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_branch.obj `if test -f 'codegen_ops_branch.c'; then $(CYGPATH_W) 'codegen_ops_branch.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_branch.c'; fi`
+
+pcem-codegen_ops_fpu_arith.o: codegen_ops_fpu_arith.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_fpu_arith.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_fpu_arith.Tpo -c -o pcem-codegen_ops_fpu_arith.o `test -f 'codegen_ops_fpu_arith.c' || echo '$(srcdir)/'`codegen_ops_fpu_arith.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_fpu_arith.Tpo $(DEPDIR)/pcem-codegen_ops_fpu_arith.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_fpu_arith.c' object='pcem-codegen_ops_fpu_arith.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_fpu_arith.o `test -f 'codegen_ops_fpu_arith.c' || echo '$(srcdir)/'`codegen_ops_fpu_arith.c
+
+pcem-codegen_ops_fpu_arith.obj: codegen_ops_fpu_arith.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_fpu_arith.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_fpu_arith.Tpo -c -o pcem-codegen_ops_fpu_arith.obj `if test -f 'codegen_ops_fpu_arith.c'; then $(CYGPATH_W) 'codegen_ops_fpu_arith.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_fpu_arith.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_fpu_arith.Tpo $(DEPDIR)/pcem-codegen_ops_fpu_arith.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_fpu_arith.c' object='pcem-codegen_ops_fpu_arith.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_fpu_arith.obj `if test -f 'codegen_ops_fpu_arith.c'; then $(CYGPATH_W) 'codegen_ops_fpu_arith.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_fpu_arith.c'; fi`
+
+pcem-codegen_ops_fpu_constant.o: codegen_ops_fpu_constant.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_fpu_constant.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_fpu_constant.Tpo -c -o pcem-codegen_ops_fpu_constant.o `test -f 'codegen_ops_fpu_constant.c' || echo '$(srcdir)/'`codegen_ops_fpu_constant.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_fpu_constant.Tpo $(DEPDIR)/pcem-codegen_ops_fpu_constant.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_fpu_constant.c' object='pcem-codegen_ops_fpu_constant.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_fpu_constant.o `test -f 'codegen_ops_fpu_constant.c' || echo '$(srcdir)/'`codegen_ops_fpu_constant.c
+
+pcem-codegen_ops_fpu_constant.obj: codegen_ops_fpu_constant.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_fpu_constant.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_fpu_constant.Tpo -c -o pcem-codegen_ops_fpu_constant.obj `if test -f 'codegen_ops_fpu_constant.c'; then $(CYGPATH_W) 'codegen_ops_fpu_constant.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_fpu_constant.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_fpu_constant.Tpo $(DEPDIR)/pcem-codegen_ops_fpu_constant.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_fpu_constant.c' object='pcem-codegen_ops_fpu_constant.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_fpu_constant.obj `if test -f 'codegen_ops_fpu_constant.c'; then $(CYGPATH_W) 'codegen_ops_fpu_constant.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_fpu_constant.c'; fi`
+
+pcem-codegen_ops_fpu_loadstore.o: codegen_ops_fpu_loadstore.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_fpu_loadstore.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_fpu_loadstore.Tpo -c -o pcem-codegen_ops_fpu_loadstore.o `test -f 'codegen_ops_fpu_loadstore.c' || echo '$(srcdir)/'`codegen_ops_fpu_loadstore.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_fpu_loadstore.Tpo $(DEPDIR)/pcem-codegen_ops_fpu_loadstore.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_fpu_loadstore.c' object='pcem-codegen_ops_fpu_loadstore.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_fpu_loadstore.o `test -f 'codegen_ops_fpu_loadstore.c' || echo '$(srcdir)/'`codegen_ops_fpu_loadstore.c
+
+pcem-codegen_ops_fpu_loadstore.obj: codegen_ops_fpu_loadstore.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_fpu_loadstore.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_fpu_loadstore.Tpo -c -o pcem-codegen_ops_fpu_loadstore.obj `if test -f 'codegen_ops_fpu_loadstore.c'; then $(CYGPATH_W) 'codegen_ops_fpu_loadstore.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_fpu_loadstore.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_fpu_loadstore.Tpo $(DEPDIR)/pcem-codegen_ops_fpu_loadstore.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_fpu_loadstore.c' object='pcem-codegen_ops_fpu_loadstore.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_fpu_loadstore.obj `if test -f 'codegen_ops_fpu_loadstore.c'; then $(CYGPATH_W) 'codegen_ops_fpu_loadstore.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_fpu_loadstore.c'; fi`
+
+pcem-codegen_ops_fpu_misc.o: codegen_ops_fpu_misc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_fpu_misc.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_fpu_misc.Tpo -c -o pcem-codegen_ops_fpu_misc.o `test -f 'codegen_ops_fpu_misc.c' || echo '$(srcdir)/'`codegen_ops_fpu_misc.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_fpu_misc.Tpo $(DEPDIR)/pcem-codegen_ops_fpu_misc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_fpu_misc.c' object='pcem-codegen_ops_fpu_misc.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_fpu_misc.o `test -f 'codegen_ops_fpu_misc.c' || echo '$(srcdir)/'`codegen_ops_fpu_misc.c
+
+pcem-codegen_ops_fpu_misc.obj: codegen_ops_fpu_misc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_fpu_misc.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_fpu_misc.Tpo -c -o pcem-codegen_ops_fpu_misc.obj `if test -f 'codegen_ops_fpu_misc.c'; then $(CYGPATH_W) 'codegen_ops_fpu_misc.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_fpu_misc.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_fpu_misc.Tpo $(DEPDIR)/pcem-codegen_ops_fpu_misc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_fpu_misc.c' object='pcem-codegen_ops_fpu_misc.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_fpu_misc.obj `if test -f 'codegen_ops_fpu_misc.c'; then $(CYGPATH_W) 'codegen_ops_fpu_misc.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_fpu_misc.c'; fi`
+
+pcem-codegen_ops_mmx_arith.o: codegen_ops_mmx_arith.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_mmx_arith.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_mmx_arith.Tpo -c -o pcem-codegen_ops_mmx_arith.o `test -f 'codegen_ops_mmx_arith.c' || echo '$(srcdir)/'`codegen_ops_mmx_arith.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_mmx_arith.Tpo $(DEPDIR)/pcem-codegen_ops_mmx_arith.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_mmx_arith.c' object='pcem-codegen_ops_mmx_arith.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_mmx_arith.o `test -f 'codegen_ops_mmx_arith.c' || echo '$(srcdir)/'`codegen_ops_mmx_arith.c
+
+pcem-codegen_ops_mmx_arith.obj: codegen_ops_mmx_arith.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_mmx_arith.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_mmx_arith.Tpo -c -o pcem-codegen_ops_mmx_arith.obj `if test -f 'codegen_ops_mmx_arith.c'; then $(CYGPATH_W) 'codegen_ops_mmx_arith.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_mmx_arith.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_mmx_arith.Tpo $(DEPDIR)/pcem-codegen_ops_mmx_arith.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_mmx_arith.c' object='pcem-codegen_ops_mmx_arith.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_mmx_arith.obj `if test -f 'codegen_ops_mmx_arith.c'; then $(CYGPATH_W) 'codegen_ops_mmx_arith.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_mmx_arith.c'; fi`
+
+pcem-codegen_ops_mmx_cmp.o: codegen_ops_mmx_cmp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_mmx_cmp.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_mmx_cmp.Tpo -c -o pcem-codegen_ops_mmx_cmp.o `test -f 'codegen_ops_mmx_cmp.c' || echo '$(srcdir)/'`codegen_ops_mmx_cmp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_mmx_cmp.Tpo $(DEPDIR)/pcem-codegen_ops_mmx_cmp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_mmx_cmp.c' object='pcem-codegen_ops_mmx_cmp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_mmx_cmp.o `test -f 'codegen_ops_mmx_cmp.c' || echo '$(srcdir)/'`codegen_ops_mmx_cmp.c
+
+pcem-codegen_ops_mmx_cmp.obj: codegen_ops_mmx_cmp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_mmx_cmp.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_mmx_cmp.Tpo -c -o pcem-codegen_ops_mmx_cmp.obj `if test -f 'codegen_ops_mmx_cmp.c'; then $(CYGPATH_W) 'codegen_ops_mmx_cmp.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_mmx_cmp.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_mmx_cmp.Tpo $(DEPDIR)/pcem-codegen_ops_mmx_cmp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_mmx_cmp.c' object='pcem-codegen_ops_mmx_cmp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_mmx_cmp.obj `if test -f 'codegen_ops_mmx_cmp.c'; then $(CYGPATH_W) 'codegen_ops_mmx_cmp.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_mmx_cmp.c'; fi`
+
+pcem-codegen_ops_mmx_loadstore.o: codegen_ops_mmx_loadstore.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_mmx_loadstore.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_mmx_loadstore.Tpo -c -o pcem-codegen_ops_mmx_loadstore.o `test -f 'codegen_ops_mmx_loadstore.c' || echo '$(srcdir)/'`codegen_ops_mmx_loadstore.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_mmx_loadstore.Tpo $(DEPDIR)/pcem-codegen_ops_mmx_loadstore.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_mmx_loadstore.c' object='pcem-codegen_ops_mmx_loadstore.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_mmx_loadstore.o `test -f 'codegen_ops_mmx_loadstore.c' || echo '$(srcdir)/'`codegen_ops_mmx_loadstore.c
+
+pcem-codegen_ops_mmx_loadstore.obj: codegen_ops_mmx_loadstore.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_mmx_loadstore.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_mmx_loadstore.Tpo -c -o pcem-codegen_ops_mmx_loadstore.obj `if test -f 'codegen_ops_mmx_loadstore.c'; then $(CYGPATH_W) 'codegen_ops_mmx_loadstore.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_mmx_loadstore.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_mmx_loadstore.Tpo $(DEPDIR)/pcem-codegen_ops_mmx_loadstore.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_mmx_loadstore.c' object='pcem-codegen_ops_mmx_loadstore.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_mmx_loadstore.obj `if test -f 'codegen_ops_mmx_loadstore.c'; then $(CYGPATH_W) 'codegen_ops_mmx_loadstore.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_mmx_loadstore.c'; fi`
+
+pcem-codegen_ops_mmx_logic.o: codegen_ops_mmx_logic.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_mmx_logic.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_mmx_logic.Tpo -c -o pcem-codegen_ops_mmx_logic.o `test -f 'codegen_ops_mmx_logic.c' || echo '$(srcdir)/'`codegen_ops_mmx_logic.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_mmx_logic.Tpo $(DEPDIR)/pcem-codegen_ops_mmx_logic.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_mmx_logic.c' object='pcem-codegen_ops_mmx_logic.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_mmx_logic.o `test -f 'codegen_ops_mmx_logic.c' || echo '$(srcdir)/'`codegen_ops_mmx_logic.c
+
+pcem-codegen_ops_mmx_logic.obj: codegen_ops_mmx_logic.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_mmx_logic.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_mmx_logic.Tpo -c -o pcem-codegen_ops_mmx_logic.obj `if test -f 'codegen_ops_mmx_logic.c'; then $(CYGPATH_W) 'codegen_ops_mmx_logic.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_mmx_logic.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_mmx_logic.Tpo $(DEPDIR)/pcem-codegen_ops_mmx_logic.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_mmx_logic.c' object='pcem-codegen_ops_mmx_logic.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_mmx_logic.obj `if test -f 'codegen_ops_mmx_logic.c'; then $(CYGPATH_W) 'codegen_ops_mmx_logic.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_mmx_logic.c'; fi`
+
+pcem-codegen_ops_mmx_pack.o: codegen_ops_mmx_pack.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_mmx_pack.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_mmx_pack.Tpo -c -o pcem-codegen_ops_mmx_pack.o `test -f 'codegen_ops_mmx_pack.c' || echo '$(srcdir)/'`codegen_ops_mmx_pack.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_mmx_pack.Tpo $(DEPDIR)/pcem-codegen_ops_mmx_pack.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_mmx_pack.c' object='pcem-codegen_ops_mmx_pack.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_mmx_pack.o `test -f 'codegen_ops_mmx_pack.c' || echo '$(srcdir)/'`codegen_ops_mmx_pack.c
+
+pcem-codegen_ops_mmx_pack.obj: codegen_ops_mmx_pack.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_mmx_pack.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_mmx_pack.Tpo -c -o pcem-codegen_ops_mmx_pack.obj `if test -f 'codegen_ops_mmx_pack.c'; then $(CYGPATH_W) 'codegen_ops_mmx_pack.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_mmx_pack.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_mmx_pack.Tpo $(DEPDIR)/pcem-codegen_ops_mmx_pack.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_mmx_pack.c' object='pcem-codegen_ops_mmx_pack.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_mmx_pack.obj `if test -f 'codegen_ops_mmx_pack.c'; then $(CYGPATH_W) 'codegen_ops_mmx_pack.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_mmx_pack.c'; fi`
+
+pcem-codegen_ops_mmx_shift.o: codegen_ops_mmx_shift.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_mmx_shift.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_mmx_shift.Tpo -c -o pcem-codegen_ops_mmx_shift.o `test -f 'codegen_ops_mmx_shift.c' || echo '$(srcdir)/'`codegen_ops_mmx_shift.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_mmx_shift.Tpo $(DEPDIR)/pcem-codegen_ops_mmx_shift.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_mmx_shift.c' object='pcem-codegen_ops_mmx_shift.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_mmx_shift.o `test -f 'codegen_ops_mmx_shift.c' || echo '$(srcdir)/'`codegen_ops_mmx_shift.c
+
+pcem-codegen_ops_mmx_shift.obj: codegen_ops_mmx_shift.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_mmx_shift.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_mmx_shift.Tpo -c -o pcem-codegen_ops_mmx_shift.obj `if test -f 'codegen_ops_mmx_shift.c'; then $(CYGPATH_W) 'codegen_ops_mmx_shift.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_mmx_shift.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_mmx_shift.Tpo $(DEPDIR)/pcem-codegen_ops_mmx_shift.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_mmx_shift.c' object='pcem-codegen_ops_mmx_shift.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_mmx_shift.obj `if test -f 'codegen_ops_mmx_shift.c'; then $(CYGPATH_W) 'codegen_ops_mmx_shift.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_mmx_shift.c'; fi`
+
+pcem-codegen_ops_helpers.o: codegen_ops_helpers.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_helpers.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_helpers.Tpo -c -o pcem-codegen_ops_helpers.o `test -f 'codegen_ops_helpers.c' || echo '$(srcdir)/'`codegen_ops_helpers.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_helpers.Tpo $(DEPDIR)/pcem-codegen_ops_helpers.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_helpers.c' object='pcem-codegen_ops_helpers.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_helpers.o `test -f 'codegen_ops_helpers.c' || echo '$(srcdir)/'`codegen_ops_helpers.c
+
+pcem-codegen_ops_helpers.obj: codegen_ops_helpers.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_helpers.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_helpers.Tpo -c -o pcem-codegen_ops_helpers.obj `if test -f 'codegen_ops_helpers.c'; then $(CYGPATH_W) 'codegen_ops_helpers.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_helpers.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_helpers.Tpo $(DEPDIR)/pcem-codegen_ops_helpers.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_helpers.c' object='pcem-codegen_ops_helpers.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_helpers.obj `if test -f 'codegen_ops_helpers.c'; then $(CYGPATH_W) 'codegen_ops_helpers.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_helpers.c'; fi`
+
+pcem-codegen_ops_jump.o: codegen_ops_jump.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_jump.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_jump.Tpo -c -o pcem-codegen_ops_jump.o `test -f 'codegen_ops_jump.c' || echo '$(srcdir)/'`codegen_ops_jump.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_jump.Tpo $(DEPDIR)/pcem-codegen_ops_jump.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_jump.c' object='pcem-codegen_ops_jump.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_jump.o `test -f 'codegen_ops_jump.c' || echo '$(srcdir)/'`codegen_ops_jump.c
+
+pcem-codegen_ops_jump.obj: codegen_ops_jump.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_jump.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_jump.Tpo -c -o pcem-codegen_ops_jump.obj `if test -f 'codegen_ops_jump.c'; then $(CYGPATH_W) 'codegen_ops_jump.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_jump.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_jump.Tpo $(DEPDIR)/pcem-codegen_ops_jump.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_jump.c' object='pcem-codegen_ops_jump.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_jump.obj `if test -f 'codegen_ops_jump.c'; then $(CYGPATH_W) 'codegen_ops_jump.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_jump.c'; fi`
+
+pcem-codegen_ops_logic.o: codegen_ops_logic.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_logic.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_logic.Tpo -c -o pcem-codegen_ops_logic.o `test -f 'codegen_ops_logic.c' || echo '$(srcdir)/'`codegen_ops_logic.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_logic.Tpo $(DEPDIR)/pcem-codegen_ops_logic.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_logic.c' object='pcem-codegen_ops_logic.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_logic.o `test -f 'codegen_ops_logic.c' || echo '$(srcdir)/'`codegen_ops_logic.c
+
+pcem-codegen_ops_logic.obj: codegen_ops_logic.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_logic.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_logic.Tpo -c -o pcem-codegen_ops_logic.obj `if test -f 'codegen_ops_logic.c'; then $(CYGPATH_W) 'codegen_ops_logic.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_logic.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_logic.Tpo $(DEPDIR)/pcem-codegen_ops_logic.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_logic.c' object='pcem-codegen_ops_logic.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_logic.obj `if test -f 'codegen_ops_logic.c'; then $(CYGPATH_W) 'codegen_ops_logic.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_logic.c'; fi`
+
+pcem-codegen_ops_shift.o: codegen_ops_shift.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_shift.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_shift.Tpo -c -o pcem-codegen_ops_shift.o `test -f 'codegen_ops_shift.c' || echo '$(srcdir)/'`codegen_ops_shift.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_shift.Tpo $(DEPDIR)/pcem-codegen_ops_shift.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_shift.c' object='pcem-codegen_ops_shift.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_shift.o `test -f 'codegen_ops_shift.c' || echo '$(srcdir)/'`codegen_ops_shift.c
+
+pcem-codegen_ops_shift.obj: codegen_ops_shift.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_shift.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_shift.Tpo -c -o pcem-codegen_ops_shift.obj `if test -f 'codegen_ops_shift.c'; then $(CYGPATH_W) 'codegen_ops_shift.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_shift.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_shift.Tpo $(DEPDIR)/pcem-codegen_ops_shift.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_shift.c' object='pcem-codegen_ops_shift.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_shift.obj `if test -f 'codegen_ops_shift.c'; then $(CYGPATH_W) 'codegen_ops_shift.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_shift.c'; fi`
+
+pcem-codegen_ops_misc.o: codegen_ops_misc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_misc.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_misc.Tpo -c -o pcem-codegen_ops_misc.o `test -f 'codegen_ops_misc.c' || echo '$(srcdir)/'`codegen_ops_misc.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_misc.Tpo $(DEPDIR)/pcem-codegen_ops_misc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_misc.c' object='pcem-codegen_ops_misc.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_misc.o `test -f 'codegen_ops_misc.c' || echo '$(srcdir)/'`codegen_ops_misc.c
+
+pcem-codegen_ops_misc.obj: codegen_ops_misc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_misc.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_misc.Tpo -c -o pcem-codegen_ops_misc.obj `if test -f 'codegen_ops_misc.c'; then $(CYGPATH_W) 'codegen_ops_misc.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_misc.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_misc.Tpo $(DEPDIR)/pcem-codegen_ops_misc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_misc.c' object='pcem-codegen_ops_misc.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_misc.obj `if test -f 'codegen_ops_misc.c'; then $(CYGPATH_W) 'codegen_ops_misc.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_misc.c'; fi`
+
+pcem-codegen_ops_mov.o: codegen_ops_mov.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_mov.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_mov.Tpo -c -o pcem-codegen_ops_mov.o `test -f 'codegen_ops_mov.c' || echo '$(srcdir)/'`codegen_ops_mov.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_mov.Tpo $(DEPDIR)/pcem-codegen_ops_mov.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_mov.c' object='pcem-codegen_ops_mov.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_mov.o `test -f 'codegen_ops_mov.c' || echo '$(srcdir)/'`codegen_ops_mov.c
+
+pcem-codegen_ops_mov.obj: codegen_ops_mov.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_mov.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_mov.Tpo -c -o pcem-codegen_ops_mov.obj `if test -f 'codegen_ops_mov.c'; then $(CYGPATH_W) 'codegen_ops_mov.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_mov.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_mov.Tpo $(DEPDIR)/pcem-codegen_ops_mov.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_mov.c' object='pcem-codegen_ops_mov.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_mov.obj `if test -f 'codegen_ops_mov.c'; then $(CYGPATH_W) 'codegen_ops_mov.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_mov.c'; fi`
+
+pcem-codegen_ops_stack.o: codegen_ops_stack.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_stack.o -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_stack.Tpo -c -o pcem-codegen_ops_stack.o `test -f 'codegen_ops_stack.c' || echo '$(srcdir)/'`codegen_ops_stack.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_stack.Tpo $(DEPDIR)/pcem-codegen_ops_stack.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_stack.c' object='pcem-codegen_ops_stack.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_stack.o `test -f 'codegen_ops_stack.c' || echo '$(srcdir)/'`codegen_ops_stack.c
+
+pcem-codegen_ops_stack.obj: codegen_ops_stack.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_ops_stack.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_ops_stack.Tpo -c -o pcem-codegen_ops_stack.obj `if test -f 'codegen_ops_stack.c'; then $(CYGPATH_W) 'codegen_ops_stack.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_stack.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_ops_stack.Tpo $(DEPDIR)/pcem-codegen_ops_stack.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_ops_stack.c' object='pcem-codegen_ops_stack.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_ops_stack.obj `if test -f 'codegen_ops_stack.c'; then $(CYGPATH_W) 'codegen_ops_stack.c'; else $(CYGPATH_W) '$(srcdir)/codegen_ops_stack.c'; fi`
+
+pcem-codegen_reg.o: codegen_reg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_reg.o -MD -MP -MF $(DEPDIR)/pcem-codegen_reg.Tpo -c -o pcem-codegen_reg.o `test -f 'codegen_reg.c' || echo '$(srcdir)/'`codegen_reg.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_reg.Tpo $(DEPDIR)/pcem-codegen_reg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_reg.c' object='pcem-codegen_reg.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_reg.o `test -f 'codegen_reg.c' || echo '$(srcdir)/'`codegen_reg.c
+
+pcem-codegen_reg.obj: codegen_reg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_reg.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_reg.Tpo -c -o pcem-codegen_reg.obj `if test -f 'codegen_reg.c'; then $(CYGPATH_W) 'codegen_reg.c'; else $(CYGPATH_W) '$(srcdir)/codegen_reg.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_reg.Tpo $(DEPDIR)/pcem-codegen_reg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_reg.c' object='pcem-codegen_reg.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_reg.obj `if test -f 'codegen_reg.c'; then $(CYGPATH_W) 'codegen_reg.c'; else $(CYGPATH_W) '$(srcdir)/codegen_reg.c'; fi`
+
pcem-codegen_timing_486.o: codegen_timing_486.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_timing_486.o -MD -MP -MF $(DEPDIR)/pcem-codegen_timing_486.Tpo -c -o pcem-codegen_timing_486.o `test -f 'codegen_timing_486.c' || echo '$(srcdir)/'`codegen_timing_486.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_timing_486.Tpo $(DEPDIR)/pcem-codegen_timing_486.Po
@@ -1551,6 +2260,48 @@ pcem-codegen_timing_common.obj: codegen_timing_common.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_timing_common.obj `if test -f 'codegen_timing_common.c'; then $(CYGPATH_W) 'codegen_timing_common.c'; else $(CYGPATH_W) '$(srcdir)/codegen_timing_common.c'; fi`
+pcem-codegen_timing_cyrixiii.o: codegen_timing_cyrixiii.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_timing_cyrixiii.o -MD -MP -MF $(DEPDIR)/pcem-codegen_timing_cyrixiii.Tpo -c -o pcem-codegen_timing_cyrixiii.o `test -f 'codegen_timing_cyrixiii.c' || echo '$(srcdir)/'`codegen_timing_cyrixiii.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_timing_cyrixiii.Tpo $(DEPDIR)/pcem-codegen_timing_cyrixiii.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_timing_cyrixiii.c' object='pcem-codegen_timing_cyrixiii.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_timing_cyrixiii.o `test -f 'codegen_timing_cyrixiii.c' || echo '$(srcdir)/'`codegen_timing_cyrixiii.c
+
+pcem-codegen_timing_cyrixiii.obj: codegen_timing_cyrixiii.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_timing_cyrixiii.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_timing_cyrixiii.Tpo -c -o pcem-codegen_timing_cyrixiii.obj `if test -f 'codegen_timing_cyrixiii.c'; then $(CYGPATH_W) 'codegen_timing_cyrixiii.c'; else $(CYGPATH_W) '$(srcdir)/codegen_timing_cyrixiii.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_timing_cyrixiii.Tpo $(DEPDIR)/pcem-codegen_timing_cyrixiii.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_timing_cyrixiii.c' object='pcem-codegen_timing_cyrixiii.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_timing_cyrixiii.obj `if test -f 'codegen_timing_cyrixiii.c'; then $(CYGPATH_W) 'codegen_timing_cyrixiii.c'; else $(CYGPATH_W) '$(srcdir)/codegen_timing_cyrixiii.c'; fi`
+
+pcem-codegen_timing_k6.o: codegen_timing_k6.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_timing_k6.o -MD -MP -MF $(DEPDIR)/pcem-codegen_timing_k6.Tpo -c -o pcem-codegen_timing_k6.o `test -f 'codegen_timing_k6.c' || echo '$(srcdir)/'`codegen_timing_k6.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_timing_k6.Tpo $(DEPDIR)/pcem-codegen_timing_k6.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_timing_k6.c' object='pcem-codegen_timing_k6.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_timing_k6.o `test -f 'codegen_timing_k6.c' || echo '$(srcdir)/'`codegen_timing_k6.c
+
+pcem-codegen_timing_k6.obj: codegen_timing_k6.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_timing_k6.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_timing_k6.Tpo -c -o pcem-codegen_timing_k6.obj `if test -f 'codegen_timing_k6.c'; then $(CYGPATH_W) 'codegen_timing_k6.c'; else $(CYGPATH_W) '$(srcdir)/codegen_timing_k6.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_timing_k6.Tpo $(DEPDIR)/pcem-codegen_timing_k6.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_timing_k6.c' object='pcem-codegen_timing_k6.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_timing_k6.obj `if test -f 'codegen_timing_k6.c'; then $(CYGPATH_W) 'codegen_timing_k6.c'; else $(CYGPATH_W) '$(srcdir)/codegen_timing_k6.c'; fi`
+
+pcem-codegen_timing_p6.o: codegen_timing_p6.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_timing_p6.o -MD -MP -MF $(DEPDIR)/pcem-codegen_timing_p6.Tpo -c -o pcem-codegen_timing_p6.o `test -f 'codegen_timing_p6.c' || echo '$(srcdir)/'`codegen_timing_p6.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_timing_p6.Tpo $(DEPDIR)/pcem-codegen_timing_p6.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_timing_p6.c' object='pcem-codegen_timing_p6.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_timing_p6.o `test -f 'codegen_timing_p6.c' || echo '$(srcdir)/'`codegen_timing_p6.c
+
+pcem-codegen_timing_p6.obj: codegen_timing_p6.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_timing_p6.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_timing_p6.Tpo -c -o pcem-codegen_timing_p6.obj `if test -f 'codegen_timing_p6.c'; then $(CYGPATH_W) 'codegen_timing_p6.c'; else $(CYGPATH_W) '$(srcdir)/codegen_timing_p6.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_timing_p6.Tpo $(DEPDIR)/pcem-codegen_timing_p6.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_timing_p6.c' object='pcem-codegen_timing_p6.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_timing_p6.obj `if test -f 'codegen_timing_p6.c'; then $(CYGPATH_W) 'codegen_timing_p6.c'; else $(CYGPATH_W) '$(srcdir)/codegen_timing_p6.c'; fi`
+
pcem-codegen_timing_pentium.o: codegen_timing_pentium.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_timing_pentium.o -MD -MP -MF $(DEPDIR)/pcem-codegen_timing_pentium.Tpo -c -o pcem-codegen_timing_pentium.o `test -f 'codegen_timing_pentium.c' || echo '$(srcdir)/'`codegen_timing_pentium.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_timing_pentium.Tpo $(DEPDIR)/pcem-codegen_timing_pentium.Po
@@ -1579,6 +2330,20 @@ pcem-codegen_timing_winchip.obj: codegen_timing_winchip.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_timing_winchip.obj `if test -f 'codegen_timing_winchip.c'; then $(CYGPATH_W) 'codegen_timing_winchip.c'; else $(CYGPATH_W) '$(srcdir)/codegen_timing_winchip.c'; fi`
+pcem-codegen_timing_winchip2.o: codegen_timing_winchip2.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_timing_winchip2.o -MD -MP -MF $(DEPDIR)/pcem-codegen_timing_winchip2.Tpo -c -o pcem-codegen_timing_winchip2.o `test -f 'codegen_timing_winchip2.c' || echo '$(srcdir)/'`codegen_timing_winchip2.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_timing_winchip2.Tpo $(DEPDIR)/pcem-codegen_timing_winchip2.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_timing_winchip2.c' object='pcem-codegen_timing_winchip2.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_timing_winchip2.o `test -f 'codegen_timing_winchip2.c' || echo '$(srcdir)/'`codegen_timing_winchip2.c
+
+pcem-codegen_timing_winchip2.obj: codegen_timing_winchip2.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_timing_winchip2.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_timing_winchip2.Tpo -c -o pcem-codegen_timing_winchip2.obj `if test -f 'codegen_timing_winchip2.c'; then $(CYGPATH_W) 'codegen_timing_winchip2.c'; else $(CYGPATH_W) '$(srcdir)/codegen_timing_winchip2.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_timing_winchip2.Tpo $(DEPDIR)/pcem-codegen_timing_winchip2.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_timing_winchip2.c' object='pcem-codegen_timing_winchip2.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_timing_winchip2.obj `if test -f 'codegen_timing_winchip2.c'; then $(CYGPATH_W) 'codegen_timing_winchip2.c'; else $(CYGPATH_W) '$(srcdir)/codegen_timing_winchip2.c'; fi`
+
pcem-compaq.o: compaq.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-compaq.o -MD -MP -MF $(DEPDIR)/pcem-compaq.Tpo -c -o pcem-compaq.o `test -f 'compaq.c' || echo '$(srcdir)/'`compaq.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-compaq.Tpo $(DEPDIR)/pcem-compaq.Po
@@ -1621,6 +2386,34 @@ pcem-cpu.obj: cpu.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-cpu.obj `if test -f 'cpu.c'; then $(CYGPATH_W) 'cpu.c'; else $(CYGPATH_W) '$(srcdir)/cpu.c'; fi`
+pcem-cpu_tables.o: cpu_tables.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-cpu_tables.o -MD -MP -MF $(DEPDIR)/pcem-cpu_tables.Tpo -c -o pcem-cpu_tables.o `test -f 'cpu_tables.c' || echo '$(srcdir)/'`cpu_tables.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-cpu_tables.Tpo $(DEPDIR)/pcem-cpu_tables.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpu_tables.c' object='pcem-cpu_tables.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-cpu_tables.o `test -f 'cpu_tables.c' || echo '$(srcdir)/'`cpu_tables.c
+
+pcem-cpu_tables.obj: cpu_tables.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-cpu_tables.obj -MD -MP -MF $(DEPDIR)/pcem-cpu_tables.Tpo -c -o pcem-cpu_tables.obj `if test -f 'cpu_tables.c'; then $(CYGPATH_W) 'cpu_tables.c'; else $(CYGPATH_W) '$(srcdir)/cpu_tables.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-cpu_tables.Tpo $(DEPDIR)/pcem-cpu_tables.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cpu_tables.c' object='pcem-cpu_tables.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-cpu_tables.obj `if test -f 'cpu_tables.c'; then $(CYGPATH_W) 'cpu_tables.c'; else $(CYGPATH_W) '$(srcdir)/cpu_tables.c'; fi`
+
+pcem-cs8230.o: cs8230.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-cs8230.o -MD -MP -MF $(DEPDIR)/pcem-cs8230.Tpo -c -o pcem-cs8230.o `test -f 'cs8230.c' || echo '$(srcdir)/'`cs8230.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-cs8230.Tpo $(DEPDIR)/pcem-cs8230.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cs8230.c' object='pcem-cs8230.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-cs8230.o `test -f 'cs8230.c' || echo '$(srcdir)/'`cs8230.c
+
+pcem-cs8230.obj: cs8230.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-cs8230.obj -MD -MP -MF $(DEPDIR)/pcem-cs8230.Tpo -c -o pcem-cs8230.obj `if test -f 'cs8230.c'; then $(CYGPATH_W) 'cs8230.c'; else $(CYGPATH_W) '$(srcdir)/cs8230.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-cs8230.Tpo $(DEPDIR)/pcem-cs8230.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cs8230.c' object='pcem-cs8230.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-cs8230.obj `if test -f 'cs8230.c'; then $(CYGPATH_W) 'cs8230.c'; else $(CYGPATH_W) '$(srcdir)/cs8230.c'; fi`
+
pcem-dells200.o: dells200.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-dells200.o -MD -MP -MF $(DEPDIR)/pcem-dells200.Tpo -c -o pcem-dells200.o `test -f 'dells200.c' || echo '$(srcdir)/'`dells200.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-dells200.Tpo $(DEPDIR)/pcem-dells200.Po
@@ -1733,6 +2526,20 @@ pcem-esdi_at.obj: esdi_at.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-esdi_at.obj `if test -f 'esdi_at.c'; then $(CYGPATH_W) 'esdi_at.c'; else $(CYGPATH_W) '$(srcdir)/esdi_at.c'; fi`
+pcem-f82c710_upc.o: f82c710_upc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-f82c710_upc.o -MD -MP -MF $(DEPDIR)/pcem-f82c710_upc.Tpo -c -o pcem-f82c710_upc.o `test -f 'f82c710_upc.c' || echo '$(srcdir)/'`f82c710_upc.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-f82c710_upc.Tpo $(DEPDIR)/pcem-f82c710_upc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='f82c710_upc.c' object='pcem-f82c710_upc.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-f82c710_upc.o `test -f 'f82c710_upc.c' || echo '$(srcdir)/'`f82c710_upc.c
+
+pcem-f82c710_upc.obj: f82c710_upc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-f82c710_upc.obj -MD -MP -MF $(DEPDIR)/pcem-f82c710_upc.Tpo -c -o pcem-f82c710_upc.obj `if test -f 'f82c710_upc.c'; then $(CYGPATH_W) 'f82c710_upc.c'; else $(CYGPATH_W) '$(srcdir)/f82c710_upc.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-f82c710_upc.Tpo $(DEPDIR)/pcem-f82c710_upc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='f82c710_upc.c' object='pcem-f82c710_upc.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-f82c710_upc.obj `if test -f 'f82c710_upc.c'; then $(CYGPATH_W) 'f82c710_upc.c'; else $(CYGPATH_W) '$(srcdir)/f82c710_upc.c'; fi`
+
pcem-fdc.o: fdc.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-fdc.o -MD -MP -MF $(DEPDIR)/pcem-fdc.Tpo -c -o pcem-fdc.o `test -f 'fdc.c' || echo '$(srcdir)/'`fdc.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-fdc.Tpo $(DEPDIR)/pcem-fdc.Po
@@ -1761,6 +2568,20 @@ pcem-fdc37c665.obj: fdc37c665.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-fdc37c665.obj `if test -f 'fdc37c665.c'; then $(CYGPATH_W) 'fdc37c665.c'; else $(CYGPATH_W) '$(srcdir)/fdc37c665.c'; fi`
+pcem-fdc37c93x.o: fdc37c93x.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-fdc37c93x.o -MD -MP -MF $(DEPDIR)/pcem-fdc37c93x.Tpo -c -o pcem-fdc37c93x.o `test -f 'fdc37c93x.c' || echo '$(srcdir)/'`fdc37c93x.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-fdc37c93x.Tpo $(DEPDIR)/pcem-fdc37c93x.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fdc37c93x.c' object='pcem-fdc37c93x.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-fdc37c93x.o `test -f 'fdc37c93x.c' || echo '$(srcdir)/'`fdc37c93x.c
+
+pcem-fdc37c93x.obj: fdc37c93x.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-fdc37c93x.obj -MD -MP -MF $(DEPDIR)/pcem-fdc37c93x.Tpo -c -o pcem-fdc37c93x.obj `if test -f 'fdc37c93x.c'; then $(CYGPATH_W) 'fdc37c93x.c'; else $(CYGPATH_W) '$(srcdir)/fdc37c93x.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-fdc37c93x.Tpo $(DEPDIR)/pcem-fdc37c93x.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fdc37c93x.c' object='pcem-fdc37c93x.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-fdc37c93x.obj `if test -f 'fdc37c93x.c'; then $(CYGPATH_W) 'fdc37c93x.c'; else $(CYGPATH_W) '$(srcdir)/fdc37c93x.c'; fi`
+
pcem-fdd.o: fdd.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-fdd.o -MD -MP -MF $(DEPDIR)/pcem-fdd.Tpo -c -o pcem-fdd.o `test -f 'fdd.c' || echo '$(srcdir)/'`fdd.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-fdd.Tpo $(DEPDIR)/pcem-fdd.Po
@@ -1887,6 +2708,20 @@ pcem-i430fx.obj: i430fx.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-i430fx.obj `if test -f 'i430fx.c'; then $(CYGPATH_W) 'i430fx.c'; else $(CYGPATH_W) '$(srcdir)/i430fx.c'; fi`
+pcem-i430hx.o: i430hx.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-i430hx.o -MD -MP -MF $(DEPDIR)/pcem-i430hx.Tpo -c -o pcem-i430hx.o `test -f 'i430hx.c' || echo '$(srcdir)/'`i430hx.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-i430hx.Tpo $(DEPDIR)/pcem-i430hx.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='i430hx.c' object='pcem-i430hx.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-i430hx.o `test -f 'i430hx.c' || echo '$(srcdir)/'`i430hx.c
+
+pcem-i430hx.obj: i430hx.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-i430hx.obj -MD -MP -MF $(DEPDIR)/pcem-i430hx.Tpo -c -o pcem-i430hx.obj `if test -f 'i430hx.c'; then $(CYGPATH_W) 'i430hx.c'; else $(CYGPATH_W) '$(srcdir)/i430hx.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-i430hx.Tpo $(DEPDIR)/pcem-i430hx.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='i430hx.c' object='pcem-i430hx.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-i430hx.obj `if test -f 'i430hx.c'; then $(CYGPATH_W) 'i430hx.c'; else $(CYGPATH_W) '$(srcdir)/i430hx.c'; fi`
+
pcem-i430vx.o: i430vx.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-i430vx.o -MD -MP -MF $(DEPDIR)/pcem-i430vx.Tpo -c -o pcem-i430vx.o `test -f 'i430vx.c' || echo '$(srcdir)/'`i430vx.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-i430vx.Tpo $(DEPDIR)/pcem-i430vx.Po
@@ -1901,6 +2736,34 @@ pcem-i430vx.obj: i430vx.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-i430vx.obj `if test -f 'i430vx.c'; then $(CYGPATH_W) 'i430vx.c'; else $(CYGPATH_W) '$(srcdir)/i430vx.c'; fi`
+pcem-i440fx.o: i440fx.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-i440fx.o -MD -MP -MF $(DEPDIR)/pcem-i440fx.Tpo -c -o pcem-i440fx.o `test -f 'i440fx.c' || echo '$(srcdir)/'`i440fx.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-i440fx.Tpo $(DEPDIR)/pcem-i440fx.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='i440fx.c' object='pcem-i440fx.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-i440fx.o `test -f 'i440fx.c' || echo '$(srcdir)/'`i440fx.c
+
+pcem-i440fx.obj: i440fx.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-i440fx.obj -MD -MP -MF $(DEPDIR)/pcem-i440fx.Tpo -c -o pcem-i440fx.obj `if test -f 'i440fx.c'; then $(CYGPATH_W) 'i440fx.c'; else $(CYGPATH_W) '$(srcdir)/i440fx.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-i440fx.Tpo $(DEPDIR)/pcem-i440fx.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='i440fx.c' object='pcem-i440fx.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-i440fx.obj `if test -f 'i440fx.c'; then $(CYGPATH_W) 'i440fx.c'; else $(CYGPATH_W) '$(srcdir)/i440fx.c'; fi`
+
+pcem-i440bx.o: i440bx.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-i440bx.o -MD -MP -MF $(DEPDIR)/pcem-i440bx.Tpo -c -o pcem-i440bx.o `test -f 'i440bx.c' || echo '$(srcdir)/'`i440bx.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-i440bx.Tpo $(DEPDIR)/pcem-i440bx.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='i440bx.c' object='pcem-i440bx.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-i440bx.o `test -f 'i440bx.c' || echo '$(srcdir)/'`i440bx.c
+
+pcem-i440bx.obj: i440bx.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-i440bx.obj -MD -MP -MF $(DEPDIR)/pcem-i440bx.Tpo -c -o pcem-i440bx.obj `if test -f 'i440bx.c'; then $(CYGPATH_W) 'i440bx.c'; else $(CYGPATH_W) '$(srcdir)/i440bx.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-i440bx.Tpo $(DEPDIR)/pcem-i440bx.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='i440bx.c' object='pcem-i440bx.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-i440bx.obj `if test -f 'i440bx.c'; then $(CYGPATH_W) 'i440bx.c'; else $(CYGPATH_W) '$(srcdir)/i440bx.c'; fi`
+
pcem-ide.o: ide.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-ide.o -MD -MP -MF $(DEPDIR)/pcem-ide.Tpo -c -o pcem-ide.o `test -f 'ide.c' || echo '$(srcdir)/'`ide.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-ide.Tpo $(DEPDIR)/pcem-ide.Po
@@ -1929,6 +2792,20 @@ pcem-ide_atapi.obj: ide_atapi.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-ide_atapi.obj `if test -f 'ide_atapi.c'; then $(CYGPATH_W) 'ide_atapi.c'; else $(CYGPATH_W) '$(srcdir)/ide_atapi.c'; fi`
+pcem-ide_sff8038i.o: ide_sff8038i.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-ide_sff8038i.o -MD -MP -MF $(DEPDIR)/pcem-ide_sff8038i.Tpo -c -o pcem-ide_sff8038i.o `test -f 'ide_sff8038i.c' || echo '$(srcdir)/'`ide_sff8038i.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-ide_sff8038i.Tpo $(DEPDIR)/pcem-ide_sff8038i.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ide_sff8038i.c' object='pcem-ide_sff8038i.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-ide_sff8038i.o `test -f 'ide_sff8038i.c' || echo '$(srcdir)/'`ide_sff8038i.c
+
+pcem-ide_sff8038i.obj: ide_sff8038i.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-ide_sff8038i.obj -MD -MP -MF $(DEPDIR)/pcem-ide_sff8038i.Tpo -c -o pcem-ide_sff8038i.obj `if test -f 'ide_sff8038i.c'; then $(CYGPATH_W) 'ide_sff8038i.c'; else $(CYGPATH_W) '$(srcdir)/ide_sff8038i.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-ide_sff8038i.Tpo $(DEPDIR)/pcem-ide_sff8038i.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ide_sff8038i.c' object='pcem-ide_sff8038i.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-ide_sff8038i.obj `if test -f 'ide_sff8038i.c'; then $(CYGPATH_W) 'ide_sff8038i.c'; else $(CYGPATH_W) '$(srcdir)/ide_sff8038i.c'; fi`
+
pcem-intel.o: intel.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-intel.o -MD -MP -MF $(DEPDIR)/pcem-intel.Tpo -c -o pcem-intel.o `test -f 'intel.c' || echo '$(srcdir)/'`intel.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-intel.Tpo $(DEPDIR)/pcem-intel.Po
@@ -2335,6 +3212,20 @@ pcem-mouse_serial.obj: mouse_serial.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-mouse_serial.obj `if test -f 'mouse_serial.c'; then $(CYGPATH_W) 'mouse_serial.c'; else $(CYGPATH_W) '$(srcdir)/mouse_serial.c'; fi`
+pcem-mvp3.o: mvp3.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-mvp3.o -MD -MP -MF $(DEPDIR)/pcem-mvp3.Tpo -c -o pcem-mvp3.o `test -f 'mvp3.c' || echo '$(srcdir)/'`mvp3.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-mvp3.Tpo $(DEPDIR)/pcem-mvp3.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mvp3.c' object='pcem-mvp3.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-mvp3.o `test -f 'mvp3.c' || echo '$(srcdir)/'`mvp3.c
+
+pcem-mvp3.obj: mvp3.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-mvp3.obj -MD -MP -MF $(DEPDIR)/pcem-mvp3.Tpo -c -o pcem-mvp3.obj `if test -f 'mvp3.c'; then $(CYGPATH_W) 'mvp3.c'; else $(CYGPATH_W) '$(srcdir)/mvp3.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-mvp3.Tpo $(DEPDIR)/pcem-mvp3.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mvp3.c' object='pcem-mvp3.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-mvp3.obj `if test -f 'mvp3.c'; then $(CYGPATH_W) 'mvp3.c'; else $(CYGPATH_W) '$(srcdir)/mvp3.c'; fi`
+
pcem-neat.o: neat.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-neat.o -MD -MP -MF $(DEPDIR)/pcem-neat.Tpo -c -o pcem-neat.o `test -f 'neat.c' || echo '$(srcdir)/'`neat.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-neat.Tpo $(DEPDIR)/pcem-neat.Po
@@ -2447,6 +3338,20 @@ pcem-pc87306.obj: pc87306.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-pc87306.obj `if test -f 'pc87306.c'; then $(CYGPATH_W) 'pc87306.c'; else $(CYGPATH_W) '$(srcdir)/pc87306.c'; fi`
+pcem-pc87307.o: pc87307.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-pc87307.o -MD -MP -MF $(DEPDIR)/pcem-pc87307.Tpo -c -o pcem-pc87307.o `test -f 'pc87307.c' || echo '$(srcdir)/'`pc87307.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-pc87307.Tpo $(DEPDIR)/pcem-pc87307.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pc87307.c' object='pcem-pc87307.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-pc87307.o `test -f 'pc87307.c' || echo '$(srcdir)/'`pc87307.c
+
+pcem-pc87307.obj: pc87307.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-pc87307.obj -MD -MP -MF $(DEPDIR)/pcem-pc87307.Tpo -c -o pcem-pc87307.obj `if test -f 'pc87307.c'; then $(CYGPATH_W) 'pc87307.c'; else $(CYGPATH_W) '$(srcdir)/pc87307.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-pc87307.Tpo $(DEPDIR)/pcem-pc87307.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pc87307.c' object='pcem-pc87307.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-pc87307.obj `if test -f 'pc87307.c'; then $(CYGPATH_W) 'pc87307.c'; else $(CYGPATH_W) '$(srcdir)/pc87307.c'; fi`
+
pcem-pci.o: pci.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-pci.o -MD -MP -MF $(DEPDIR)/pcem-pci.Tpo -c -o pcem-pci.o `test -f 'pci.c' || echo '$(srcdir)/'`pci.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-pci.Tpo $(DEPDIR)/pcem-pci.Po
@@ -2489,6 +3394,20 @@ pcem-piix.obj: piix.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-piix.obj `if test -f 'piix.c'; then $(CYGPATH_W) 'piix.c'; else $(CYGPATH_W) '$(srcdir)/piix.c'; fi`
+pcem-piix_pm.o: piix_pm.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-piix_pm.o -MD -MP -MF $(DEPDIR)/pcem-piix_pm.Tpo -c -o pcem-piix_pm.o `test -f 'piix_pm.c' || echo '$(srcdir)/'`piix_pm.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-piix_pm.Tpo $(DEPDIR)/pcem-piix_pm.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='piix_pm.c' object='pcem-piix_pm.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-piix_pm.o `test -f 'piix_pm.c' || echo '$(srcdir)/'`piix_pm.c
+
+pcem-piix_pm.obj: piix_pm.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-piix_pm.obj -MD -MP -MF $(DEPDIR)/pcem-piix_pm.Tpo -c -o pcem-piix_pm.obj `if test -f 'piix_pm.c'; then $(CYGPATH_W) 'piix_pm.c'; else $(CYGPATH_W) '$(srcdir)/piix_pm.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-piix_pm.Tpo $(DEPDIR)/pcem-piix_pm.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='piix_pm.c' object='pcem-piix_pm.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-piix_pm.obj `if test -f 'piix_pm.c'; then $(CYGPATH_W) 'piix_pm.c'; else $(CYGPATH_W) '$(srcdir)/piix_pm.c'; fi`
+
pcem-pit.o: pit.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-pit.o -MD -MP -MF $(DEPDIR)/pcem-pit.Tpo -c -o pcem-pit.o `test -f 'pit.c' || echo '$(srcdir)/'`pit.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-pit.Tpo $(DEPDIR)/pcem-pit.Po
@@ -2587,6 +3506,20 @@ pcem-nvr_tc8521.obj: nvr_tc8521.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-nvr_tc8521.obj `if test -f 'nvr_tc8521.c'; then $(CYGPATH_W) 'nvr_tc8521.c'; else $(CYGPATH_W) '$(srcdir)/nvr_tc8521.c'; fi`
+pcem-pzx.o: pzx.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-pzx.o -MD -MP -MF $(DEPDIR)/pcem-pzx.Tpo -c -o pcem-pzx.o `test -f 'pzx.c' || echo '$(srcdir)/'`pzx.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-pzx.Tpo $(DEPDIR)/pcem-pzx.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pzx.c' object='pcem-pzx.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-pzx.o `test -f 'pzx.c' || echo '$(srcdir)/'`pzx.c
+
+pcem-pzx.obj: pzx.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-pzx.obj -MD -MP -MF $(DEPDIR)/pcem-pzx.Tpo -c -o pcem-pzx.obj `if test -f 'pzx.c'; then $(CYGPATH_W) 'pzx.c'; else $(CYGPATH_W) '$(srcdir)/pzx.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-pzx.Tpo $(DEPDIR)/pcem-pzx.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pzx.c' object='pcem-pzx.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-pzx.obj `if test -f 'pzx.c'; then $(CYGPATH_W) 'pzx.c'; else $(CYGPATH_W) '$(srcdir)/pzx.c'; fi`
+
pcem-rom.o: rom.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-rom.o -MD -MP -MF $(DEPDIR)/pcem-rom.Tpo -c -o pcem-rom.o `test -f 'rom.c' || echo '$(srcdir)/'`rom.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-rom.Tpo $(DEPDIR)/pcem-rom.Po
@@ -2629,6 +3562,20 @@ pcem-rtc_tc8521.obj: rtc_tc8521.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-rtc_tc8521.obj `if test -f 'rtc_tc8521.c'; then $(CYGPATH_W) 'rtc_tc8521.c'; else $(CYGPATH_W) '$(srcdir)/rtc_tc8521.c'; fi`
+pcem-scamp.o: scamp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-scamp.o -MD -MP -MF $(DEPDIR)/pcem-scamp.Tpo -c -o pcem-scamp.o `test -f 'scamp.c' || echo '$(srcdir)/'`scamp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-scamp.Tpo $(DEPDIR)/pcem-scamp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='scamp.c' object='pcem-scamp.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-scamp.o `test -f 'scamp.c' || echo '$(srcdir)/'`scamp.c
+
+pcem-scamp.obj: scamp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-scamp.obj -MD -MP -MF $(DEPDIR)/pcem-scamp.Tpo -c -o pcem-scamp.obj `if test -f 'scamp.c'; then $(CYGPATH_W) 'scamp.c'; else $(CYGPATH_W) '$(srcdir)/scamp.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-scamp.Tpo $(DEPDIR)/pcem-scamp.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='scamp.c' object='pcem-scamp.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-scamp.obj `if test -f 'scamp.c'; then $(CYGPATH_W) 'scamp.c'; else $(CYGPATH_W) '$(srcdir)/scamp.c'; fi`
+
pcem-scat.o: scat.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-scat.o -MD -MP -MF $(DEPDIR)/pcem-scat.Tpo -c -o pcem-scat.o `test -f 'scat.c' || echo '$(srcdir)/'`scat.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-scat.Tpo $(DEPDIR)/pcem-scat.Po
@@ -2713,6 +3660,20 @@ pcem-scsi_hd.obj: scsi_hd.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-scsi_hd.obj `if test -f 'scsi_hd.c'; then $(CYGPATH_W) 'scsi_hd.c'; else $(CYGPATH_W) '$(srcdir)/scsi_hd.c'; fi`
+pcem-scsi_ibm.o: scsi_ibm.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-scsi_ibm.o -MD -MP -MF $(DEPDIR)/pcem-scsi_ibm.Tpo -c -o pcem-scsi_ibm.o `test -f 'scsi_ibm.c' || echo '$(srcdir)/'`scsi_ibm.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-scsi_ibm.Tpo $(DEPDIR)/pcem-scsi_ibm.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='scsi_ibm.c' object='pcem-scsi_ibm.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-scsi_ibm.o `test -f 'scsi_ibm.c' || echo '$(srcdir)/'`scsi_ibm.c
+
+pcem-scsi_ibm.obj: scsi_ibm.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-scsi_ibm.obj -MD -MP -MF $(DEPDIR)/pcem-scsi_ibm.Tpo -c -o pcem-scsi_ibm.obj `if test -f 'scsi_ibm.c'; then $(CYGPATH_W) 'scsi_ibm.c'; else $(CYGPATH_W) '$(srcdir)/scsi_ibm.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-scsi_ibm.Tpo $(DEPDIR)/pcem-scsi_ibm.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='scsi_ibm.c' object='pcem-scsi_ibm.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-scsi_ibm.obj `if test -f 'scsi_ibm.c'; then $(CYGPATH_W) 'scsi_ibm.c'; else $(CYGPATH_W) '$(srcdir)/scsi_ibm.c'; fi`
+
pcem-scsi_zip.o: scsi_zip.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-scsi_zip.o -MD -MP -MF $(DEPDIR)/pcem-scsi_zip.Tpo -c -o pcem-scsi_zip.o `test -f 'scsi_zip.c' || echo '$(srcdir)/'`scsi_zip.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-scsi_zip.Tpo $(DEPDIR)/pcem-scsi_zip.Po
@@ -2853,6 +3814,20 @@ pcem-sound_audiopci.obj: sound_audiopci.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-sound_audiopci.obj `if test -f 'sound_audiopci.c'; then $(CYGPATH_W) 'sound_audiopci.c'; else $(CYGPATH_W) '$(srcdir)/sound_audiopci.c'; fi`
+pcem-sound_azt2316a.o: sound_azt2316a.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-sound_azt2316a.o -MD -MP -MF $(DEPDIR)/pcem-sound_azt2316a.Tpo -c -o pcem-sound_azt2316a.o `test -f 'sound_azt2316a.c' || echo '$(srcdir)/'`sound_azt2316a.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-sound_azt2316a.Tpo $(DEPDIR)/pcem-sound_azt2316a.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sound_azt2316a.c' object='pcem-sound_azt2316a.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-sound_azt2316a.o `test -f 'sound_azt2316a.c' || echo '$(srcdir)/'`sound_azt2316a.c
+
+pcem-sound_azt2316a.obj: sound_azt2316a.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-sound_azt2316a.obj -MD -MP -MF $(DEPDIR)/pcem-sound_azt2316a.Tpo -c -o pcem-sound_azt2316a.obj `if test -f 'sound_azt2316a.c'; then $(CYGPATH_W) 'sound_azt2316a.c'; else $(CYGPATH_W) '$(srcdir)/sound_azt2316a.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-sound_azt2316a.Tpo $(DEPDIR)/pcem-sound_azt2316a.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sound_azt2316a.c' object='pcem-sound_azt2316a.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-sound_azt2316a.obj `if test -f 'sound_azt2316a.c'; then $(CYGPATH_W) 'sound_azt2316a.c'; else $(CYGPATH_W) '$(srcdir)/sound_azt2316a.c'; fi`
+
pcem-sound_cms.o: sound_cms.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-sound_cms.o -MD -MP -MF $(DEPDIR)/pcem-sound_cms.Tpo -c -o pcem-sound_cms.o `test -f 'sound_cms.c' || echo '$(srcdir)/'`sound_cms.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-sound_cms.Tpo $(DEPDIR)/pcem-sound_cms.Po
@@ -3077,6 +4052,34 @@ pcem-soundopenal.obj: soundopenal.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-soundopenal.obj `if test -f 'soundopenal.c'; then $(CYGPATH_W) 'soundopenal.c'; else $(CYGPATH_W) '$(srcdir)/soundopenal.c'; fi`
+pcem-sst39sf010.o: sst39sf010.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-sst39sf010.o -MD -MP -MF $(DEPDIR)/pcem-sst39sf010.Tpo -c -o pcem-sst39sf010.o `test -f 'sst39sf010.c' || echo '$(srcdir)/'`sst39sf010.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-sst39sf010.Tpo $(DEPDIR)/pcem-sst39sf010.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sst39sf010.c' object='pcem-sst39sf010.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-sst39sf010.o `test -f 'sst39sf010.c' || echo '$(srcdir)/'`sst39sf010.c
+
+pcem-sst39sf010.obj: sst39sf010.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-sst39sf010.obj -MD -MP -MF $(DEPDIR)/pcem-sst39sf010.Tpo -c -o pcem-sst39sf010.obj `if test -f 'sst39sf010.c'; then $(CYGPATH_W) 'sst39sf010.c'; else $(CYGPATH_W) '$(srcdir)/sst39sf010.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-sst39sf010.Tpo $(DEPDIR)/pcem-sst39sf010.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sst39sf010.c' object='pcem-sst39sf010.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-sst39sf010.obj `if test -f 'sst39sf010.c'; then $(CYGPATH_W) 'sst39sf010.c'; else $(CYGPATH_W) '$(srcdir)/sst39sf010.c'; fi`
+
+pcem-superxt.o: superxt.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-superxt.o -MD -MP -MF $(DEPDIR)/pcem-superxt.Tpo -c -o pcem-superxt.o `test -f 'superxt.c' || echo '$(srcdir)/'`superxt.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-superxt.Tpo $(DEPDIR)/pcem-superxt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='superxt.c' object='pcem-superxt.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-superxt.o `test -f 'superxt.c' || echo '$(srcdir)/'`superxt.c
+
+pcem-superxt.obj: superxt.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-superxt.obj -MD -MP -MF $(DEPDIR)/pcem-superxt.Tpo -c -o pcem-superxt.obj `if test -f 'superxt.c'; then $(CYGPATH_W) 'superxt.c'; else $(CYGPATH_W) '$(srcdir)/superxt.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-superxt.Tpo $(DEPDIR)/pcem-superxt.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='superxt.c' object='pcem-superxt.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-superxt.obj `if test -f 'superxt.c'; then $(CYGPATH_W) 'superxt.c'; else $(CYGPATH_W) '$(srcdir)/superxt.c'; fi`
+
pcem-tandy_eeprom.o: tandy_eeprom.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-tandy_eeprom.o -MD -MP -MF $(DEPDIR)/pcem-tandy_eeprom.Tpo -c -o pcem-tandy_eeprom.o `test -f 'tandy_eeprom.c' || echo '$(srcdir)/'`tandy_eeprom.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-tandy_eeprom.Tpo $(DEPDIR)/pcem-tandy_eeprom.Po
@@ -3301,6 +4304,20 @@ pcem-vid_compaq_cga.obj: vid_compaq_cga.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_compaq_cga.obj `if test -f 'vid_compaq_cga.c'; then $(CYGPATH_W) 'vid_compaq_cga.c'; else $(CYGPATH_W) '$(srcdir)/vid_compaq_cga.c'; fi`
+pcem-vid_ddc.o: vid_ddc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_ddc.o -MD -MP -MF $(DEPDIR)/pcem-vid_ddc.Tpo -c -o pcem-vid_ddc.o `test -f 'vid_ddc.c' || echo '$(srcdir)/'`vid_ddc.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_ddc.Tpo $(DEPDIR)/pcem-vid_ddc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_ddc.c' object='pcem-vid_ddc.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_ddc.o `test -f 'vid_ddc.c' || echo '$(srcdir)/'`vid_ddc.c
+
+pcem-vid_ddc.obj: vid_ddc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_ddc.obj -MD -MP -MF $(DEPDIR)/pcem-vid_ddc.Tpo -c -o pcem-vid_ddc.obj `if test -f 'vid_ddc.c'; then $(CYGPATH_W) 'vid_ddc.c'; else $(CYGPATH_W) '$(srcdir)/vid_ddc.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_ddc.Tpo $(DEPDIR)/pcem-vid_ddc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_ddc.c' object='pcem-vid_ddc.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_ddc.obj `if test -f 'vid_ddc.c'; then $(CYGPATH_W) 'vid_ddc.c'; else $(CYGPATH_W) '$(srcdir)/vid_ddc.c'; fi`
+
pcem-vid_ega.o: vid_ega.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_ega.o -MD -MP -MF $(DEPDIR)/pcem-vid_ega.Tpo -c -o pcem-vid_ega.o `test -f 'vid_ega.c' || echo '$(srcdir)/'`vid_ega.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_ega.Tpo $(DEPDIR)/pcem-vid_ega.Po
@@ -3371,6 +4388,20 @@ pcem-vid_hercules.obj: vid_hercules.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_hercules.obj `if test -f 'vid_hercules.c'; then $(CYGPATH_W) 'vid_hercules.c'; else $(CYGPATH_W) '$(srcdir)/vid_hercules.c'; fi`
+pcem-vid_ht216.o: vid_ht216.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_ht216.o -MD -MP -MF $(DEPDIR)/pcem-vid_ht216.Tpo -c -o pcem-vid_ht216.o `test -f 'vid_ht216.c' || echo '$(srcdir)/'`vid_ht216.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_ht216.Tpo $(DEPDIR)/pcem-vid_ht216.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_ht216.c' object='pcem-vid_ht216.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_ht216.o `test -f 'vid_ht216.c' || echo '$(srcdir)/'`vid_ht216.c
+
+pcem-vid_ht216.obj: vid_ht216.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_ht216.obj -MD -MP -MF $(DEPDIR)/pcem-vid_ht216.Tpo -c -o pcem-vid_ht216.obj `if test -f 'vid_ht216.c'; then $(CYGPATH_W) 'vid_ht216.c'; else $(CYGPATH_W) '$(srcdir)/vid_ht216.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_ht216.Tpo $(DEPDIR)/pcem-vid_ht216.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_ht216.c' object='pcem-vid_ht216.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_ht216.obj `if test -f 'vid_ht216.c'; then $(CYGPATH_W) 'vid_ht216.c'; else $(CYGPATH_W) '$(srcdir)/vid_ht216.c'; fi`
+
pcem-vid_icd2061.o: vid_icd2061.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_icd2061.o -MD -MP -MF $(DEPDIR)/pcem-vid_icd2061.Tpo -c -o pcem-vid_icd2061.o `test -f 'vid_icd2061.c' || echo '$(srcdir)/'`vid_icd2061.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_icd2061.Tpo $(DEPDIR)/pcem-vid_icd2061.Po
@@ -3399,6 +4430,20 @@ pcem-vid_ics2595.obj: vid_ics2595.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_ics2595.obj `if test -f 'vid_ics2595.c'; then $(CYGPATH_W) 'vid_ics2595.c'; else $(CYGPATH_W) '$(srcdir)/vid_ics2595.c'; fi`
+pcem-vid_im1024.o: vid_im1024.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_im1024.o -MD -MP -MF $(DEPDIR)/pcem-vid_im1024.Tpo -c -o pcem-vid_im1024.o `test -f 'vid_im1024.c' || echo '$(srcdir)/'`vid_im1024.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_im1024.Tpo $(DEPDIR)/pcem-vid_im1024.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_im1024.c' object='pcem-vid_im1024.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_im1024.o `test -f 'vid_im1024.c' || echo '$(srcdir)/'`vid_im1024.c
+
+pcem-vid_im1024.obj: vid_im1024.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_im1024.obj -MD -MP -MF $(DEPDIR)/pcem-vid_im1024.Tpo -c -o pcem-vid_im1024.obj `if test -f 'vid_im1024.c'; then $(CYGPATH_W) 'vid_im1024.c'; else $(CYGPATH_W) '$(srcdir)/vid_im1024.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_im1024.Tpo $(DEPDIR)/pcem-vid_im1024.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_im1024.c' object='pcem-vid_im1024.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_im1024.obj `if test -f 'vid_im1024.c'; then $(CYGPATH_W) 'vid_im1024.c'; else $(CYGPATH_W) '$(srcdir)/vid_im1024.c'; fi`
+
pcem-vid_incolor.o: vid_incolor.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_incolor.o -MD -MP -MF $(DEPDIR)/pcem-vid_incolor.Tpo -c -o pcem-vid_incolor.o `test -f 'vid_incolor.c' || echo '$(srcdir)/'`vid_incolor.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_incolor.Tpo $(DEPDIR)/pcem-vid_incolor.Po
@@ -3427,6 +4472,20 @@ pcem-vid_mda.obj: vid_mda.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_mda.obj `if test -f 'vid_mda.c'; then $(CYGPATH_W) 'vid_mda.c'; else $(CYGPATH_W) '$(srcdir)/vid_mda.c'; fi`
+pcem-vid_mga.o: vid_mga.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_mga.o -MD -MP -MF $(DEPDIR)/pcem-vid_mga.Tpo -c -o pcem-vid_mga.o `test -f 'vid_mga.c' || echo '$(srcdir)/'`vid_mga.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_mga.Tpo $(DEPDIR)/pcem-vid_mga.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_mga.c' object='pcem-vid_mga.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_mga.o `test -f 'vid_mga.c' || echo '$(srcdir)/'`vid_mga.c
+
+pcem-vid_mga.obj: vid_mga.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_mga.obj -MD -MP -MF $(DEPDIR)/pcem-vid_mga.Tpo -c -o pcem-vid_mga.obj `if test -f 'vid_mga.c'; then $(CYGPATH_W) 'vid_mga.c'; else $(CYGPATH_W) '$(srcdir)/vid_mga.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_mga.Tpo $(DEPDIR)/pcem-vid_mga.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_mga.c' object='pcem-vid_mga.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_mga.obj `if test -f 'vid_mga.c'; then $(CYGPATH_W) 'vid_mga.c'; else $(CYGPATH_W) '$(srcdir)/vid_mga.c'; fi`
+
pcem-vid_olivetti_m24.o: vid_olivetti_m24.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_olivetti_m24.o -MD -MP -MF $(DEPDIR)/pcem-vid_olivetti_m24.Tpo -c -o pcem-vid_olivetti_m24.o `test -f 'vid_olivetti_m24.c' || echo '$(srcdir)/'`vid_olivetti_m24.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_olivetti_m24.Tpo $(DEPDIR)/pcem-vid_olivetti_m24.Po
@@ -3539,6 +4598,20 @@ pcem-vid_pcjr.obj: vid_pcjr.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_pcjr.obj `if test -f 'vid_pcjr.c'; then $(CYGPATH_W) 'vid_pcjr.c'; else $(CYGPATH_W) '$(srcdir)/vid_pcjr.c'; fi`
+pcem-vid_pgc.o: vid_pgc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_pgc.o -MD -MP -MF $(DEPDIR)/pcem-vid_pgc.Tpo -c -o pcem-vid_pgc.o `test -f 'vid_pgc.c' || echo '$(srcdir)/'`vid_pgc.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_pgc.Tpo $(DEPDIR)/pcem-vid_pgc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_pgc.c' object='pcem-vid_pgc.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_pgc.o `test -f 'vid_pgc.c' || echo '$(srcdir)/'`vid_pgc.c
+
+pcem-vid_pgc.obj: vid_pgc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_pgc.obj -MD -MP -MF $(DEPDIR)/pcem-vid_pgc.Tpo -c -o pcem-vid_pgc.obj `if test -f 'vid_pgc.c'; then $(CYGPATH_W) 'vid_pgc.c'; else $(CYGPATH_W) '$(srcdir)/vid_pgc.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_pgc.Tpo $(DEPDIR)/pcem-vid_pgc.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_pgc.c' object='pcem-vid_pgc.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_pgc.obj `if test -f 'vid_pgc.c'; then $(CYGPATH_W) 'vid_pgc.c'; else $(CYGPATH_W) '$(srcdir)/vid_pgc.c'; fi`
+
pcem-vid_ps1_svga.o: vid_ps1_svga.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_ps1_svga.o -MD -MP -MF $(DEPDIR)/pcem-vid_ps1_svga.Tpo -c -o pcem-vid_ps1_svga.o `test -f 'vid_ps1_svga.c' || echo '$(srcdir)/'`vid_ps1_svga.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_ps1_svga.Tpo $(DEPDIR)/pcem-vid_ps1_svga.Po
@@ -3595,6 +4668,20 @@ pcem-vid_sdac_ramdac.obj: vid_sdac_ramdac.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_sdac_ramdac.obj `if test -f 'vid_sdac_ramdac.c'; then $(CYGPATH_W) 'vid_sdac_ramdac.c'; else $(CYGPATH_W) '$(srcdir)/vid_sdac_ramdac.c'; fi`
+pcem-vid_sigma.o: vid_sigma.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_sigma.o -MD -MP -MF $(DEPDIR)/pcem-vid_sigma.Tpo -c -o pcem-vid_sigma.o `test -f 'vid_sigma.c' || echo '$(srcdir)/'`vid_sigma.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_sigma.Tpo $(DEPDIR)/pcem-vid_sigma.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_sigma.c' object='pcem-vid_sigma.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_sigma.o `test -f 'vid_sigma.c' || echo '$(srcdir)/'`vid_sigma.c
+
+pcem-vid_sigma.obj: vid_sigma.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_sigma.obj -MD -MP -MF $(DEPDIR)/pcem-vid_sigma.Tpo -c -o pcem-vid_sigma.obj `if test -f 'vid_sigma.c'; then $(CYGPATH_W) 'vid_sigma.c'; else $(CYGPATH_W) '$(srcdir)/vid_sigma.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_sigma.Tpo $(DEPDIR)/pcem-vid_sigma.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_sigma.c' object='pcem-vid_sigma.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_sigma.obj `if test -f 'vid_sigma.c'; then $(CYGPATH_W) 'vid_sigma.c'; else $(CYGPATH_W) '$(srcdir)/vid_sigma.c'; fi`
+
pcem-vid_stg_ramdac.o: vid_stg_ramdac.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_stg_ramdac.o -MD -MP -MF $(DEPDIR)/pcem-vid_stg_ramdac.Tpo -c -o pcem-vid_stg_ramdac.o `test -f 'vid_stg_ramdac.c' || echo '$(srcdir)/'`vid_stg_ramdac.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_stg_ramdac.Tpo $(DEPDIR)/pcem-vid_stg_ramdac.Po
@@ -3777,6 +4864,146 @@ pcem-vid_voodoo.obj: vid_voodoo.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo.obj `if test -f 'vid_voodoo.c'; then $(CYGPATH_W) 'vid_voodoo.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo.c'; fi`
+pcem-vid_voodoo_banshee.o: vid_voodoo_banshee.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_banshee.o -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_banshee.Tpo -c -o pcem-vid_voodoo_banshee.o `test -f 'vid_voodoo_banshee.c' || echo '$(srcdir)/'`vid_voodoo_banshee.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_banshee.Tpo $(DEPDIR)/pcem-vid_voodoo_banshee.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_banshee.c' object='pcem-vid_voodoo_banshee.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_banshee.o `test -f 'vid_voodoo_banshee.c' || echo '$(srcdir)/'`vid_voodoo_banshee.c
+
+pcem-vid_voodoo_banshee.obj: vid_voodoo_banshee.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_banshee.obj -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_banshee.Tpo -c -o pcem-vid_voodoo_banshee.obj `if test -f 'vid_voodoo_banshee.c'; then $(CYGPATH_W) 'vid_voodoo_banshee.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_banshee.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_banshee.Tpo $(DEPDIR)/pcem-vid_voodoo_banshee.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_banshee.c' object='pcem-vid_voodoo_banshee.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_banshee.obj `if test -f 'vid_voodoo_banshee.c'; then $(CYGPATH_W) 'vid_voodoo_banshee.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_banshee.c'; fi`
+
+pcem-vid_voodoo_banshee_blitter.o: vid_voodoo_banshee_blitter.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_banshee_blitter.o -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_banshee_blitter.Tpo -c -o pcem-vid_voodoo_banshee_blitter.o `test -f 'vid_voodoo_banshee_blitter.c' || echo '$(srcdir)/'`vid_voodoo_banshee_blitter.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_banshee_blitter.Tpo $(DEPDIR)/pcem-vid_voodoo_banshee_blitter.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_banshee_blitter.c' object='pcem-vid_voodoo_banshee_blitter.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_banshee_blitter.o `test -f 'vid_voodoo_banshee_blitter.c' || echo '$(srcdir)/'`vid_voodoo_banshee_blitter.c
+
+pcem-vid_voodoo_banshee_blitter.obj: vid_voodoo_banshee_blitter.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_banshee_blitter.obj -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_banshee_blitter.Tpo -c -o pcem-vid_voodoo_banshee_blitter.obj `if test -f 'vid_voodoo_banshee_blitter.c'; then $(CYGPATH_W) 'vid_voodoo_banshee_blitter.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_banshee_blitter.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_banshee_blitter.Tpo $(DEPDIR)/pcem-vid_voodoo_banshee_blitter.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_banshee_blitter.c' object='pcem-vid_voodoo_banshee_blitter.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_banshee_blitter.obj `if test -f 'vid_voodoo_banshee_blitter.c'; then $(CYGPATH_W) 'vid_voodoo_banshee_blitter.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_banshee_blitter.c'; fi`
+
+pcem-vid_voodoo_blitter.o: vid_voodoo_blitter.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_blitter.o -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_blitter.Tpo -c -o pcem-vid_voodoo_blitter.o `test -f 'vid_voodoo_blitter.c' || echo '$(srcdir)/'`vid_voodoo_blitter.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_blitter.Tpo $(DEPDIR)/pcem-vid_voodoo_blitter.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_blitter.c' object='pcem-vid_voodoo_blitter.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_blitter.o `test -f 'vid_voodoo_blitter.c' || echo '$(srcdir)/'`vid_voodoo_blitter.c
+
+pcem-vid_voodoo_blitter.obj: vid_voodoo_blitter.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_blitter.obj -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_blitter.Tpo -c -o pcem-vid_voodoo_blitter.obj `if test -f 'vid_voodoo_blitter.c'; then $(CYGPATH_W) 'vid_voodoo_blitter.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_blitter.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_blitter.Tpo $(DEPDIR)/pcem-vid_voodoo_blitter.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_blitter.c' object='pcem-vid_voodoo_blitter.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_blitter.obj `if test -f 'vid_voodoo_blitter.c'; then $(CYGPATH_W) 'vid_voodoo_blitter.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_blitter.c'; fi`
+
+pcem-vid_voodoo_display.o: vid_voodoo_display.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_display.o -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_display.Tpo -c -o pcem-vid_voodoo_display.o `test -f 'vid_voodoo_display.c' || echo '$(srcdir)/'`vid_voodoo_display.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_display.Tpo $(DEPDIR)/pcem-vid_voodoo_display.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_display.c' object='pcem-vid_voodoo_display.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_display.o `test -f 'vid_voodoo_display.c' || echo '$(srcdir)/'`vid_voodoo_display.c
+
+pcem-vid_voodoo_display.obj: vid_voodoo_display.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_display.obj -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_display.Tpo -c -o pcem-vid_voodoo_display.obj `if test -f 'vid_voodoo_display.c'; then $(CYGPATH_W) 'vid_voodoo_display.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_display.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_display.Tpo $(DEPDIR)/pcem-vid_voodoo_display.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_display.c' object='pcem-vid_voodoo_display.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_display.obj `if test -f 'vid_voodoo_display.c'; then $(CYGPATH_W) 'vid_voodoo_display.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_display.c'; fi`
+
+pcem-vid_voodoo_fb.o: vid_voodoo_fb.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_fb.o -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_fb.Tpo -c -o pcem-vid_voodoo_fb.o `test -f 'vid_voodoo_fb.c' || echo '$(srcdir)/'`vid_voodoo_fb.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_fb.Tpo $(DEPDIR)/pcem-vid_voodoo_fb.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_fb.c' object='pcem-vid_voodoo_fb.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_fb.o `test -f 'vid_voodoo_fb.c' || echo '$(srcdir)/'`vid_voodoo_fb.c
+
+pcem-vid_voodoo_fb.obj: vid_voodoo_fb.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_fb.obj -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_fb.Tpo -c -o pcem-vid_voodoo_fb.obj `if test -f 'vid_voodoo_fb.c'; then $(CYGPATH_W) 'vid_voodoo_fb.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_fb.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_fb.Tpo $(DEPDIR)/pcem-vid_voodoo_fb.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_fb.c' object='pcem-vid_voodoo_fb.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_fb.obj `if test -f 'vid_voodoo_fb.c'; then $(CYGPATH_W) 'vid_voodoo_fb.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_fb.c'; fi`
+
+pcem-vid_voodoo_fifo.o: vid_voodoo_fifo.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_fifo.o -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_fifo.Tpo -c -o pcem-vid_voodoo_fifo.o `test -f 'vid_voodoo_fifo.c' || echo '$(srcdir)/'`vid_voodoo_fifo.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_fifo.Tpo $(DEPDIR)/pcem-vid_voodoo_fifo.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_fifo.c' object='pcem-vid_voodoo_fifo.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_fifo.o `test -f 'vid_voodoo_fifo.c' || echo '$(srcdir)/'`vid_voodoo_fifo.c
+
+pcem-vid_voodoo_fifo.obj: vid_voodoo_fifo.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_fifo.obj -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_fifo.Tpo -c -o pcem-vid_voodoo_fifo.obj `if test -f 'vid_voodoo_fifo.c'; then $(CYGPATH_W) 'vid_voodoo_fifo.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_fifo.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_fifo.Tpo $(DEPDIR)/pcem-vid_voodoo_fifo.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_fifo.c' object='pcem-vid_voodoo_fifo.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_fifo.obj `if test -f 'vid_voodoo_fifo.c'; then $(CYGPATH_W) 'vid_voodoo_fifo.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_fifo.c'; fi`
+
+pcem-vid_voodoo_reg.o: vid_voodoo_reg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_reg.o -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_reg.Tpo -c -o pcem-vid_voodoo_reg.o `test -f 'vid_voodoo_reg.c' || echo '$(srcdir)/'`vid_voodoo_reg.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_reg.Tpo $(DEPDIR)/pcem-vid_voodoo_reg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_reg.c' object='pcem-vid_voodoo_reg.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_reg.o `test -f 'vid_voodoo_reg.c' || echo '$(srcdir)/'`vid_voodoo_reg.c
+
+pcem-vid_voodoo_reg.obj: vid_voodoo_reg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_reg.obj -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_reg.Tpo -c -o pcem-vid_voodoo_reg.obj `if test -f 'vid_voodoo_reg.c'; then $(CYGPATH_W) 'vid_voodoo_reg.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_reg.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_reg.Tpo $(DEPDIR)/pcem-vid_voodoo_reg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_reg.c' object='pcem-vid_voodoo_reg.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_reg.obj `if test -f 'vid_voodoo_reg.c'; then $(CYGPATH_W) 'vid_voodoo_reg.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_reg.c'; fi`
+
+pcem-vid_voodoo_render.o: vid_voodoo_render.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_render.o -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_render.Tpo -c -o pcem-vid_voodoo_render.o `test -f 'vid_voodoo_render.c' || echo '$(srcdir)/'`vid_voodoo_render.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_render.Tpo $(DEPDIR)/pcem-vid_voodoo_render.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_render.c' object='pcem-vid_voodoo_render.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_render.o `test -f 'vid_voodoo_render.c' || echo '$(srcdir)/'`vid_voodoo_render.c
+
+pcem-vid_voodoo_render.obj: vid_voodoo_render.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_render.obj -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_render.Tpo -c -o pcem-vid_voodoo_render.obj `if test -f 'vid_voodoo_render.c'; then $(CYGPATH_W) 'vid_voodoo_render.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_render.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_render.Tpo $(DEPDIR)/pcem-vid_voodoo_render.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_render.c' object='pcem-vid_voodoo_render.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_render.obj `if test -f 'vid_voodoo_render.c'; then $(CYGPATH_W) 'vid_voodoo_render.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_render.c'; fi`
+
+pcem-vid_voodoo_setup.o: vid_voodoo_setup.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_setup.o -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_setup.Tpo -c -o pcem-vid_voodoo_setup.o `test -f 'vid_voodoo_setup.c' || echo '$(srcdir)/'`vid_voodoo_setup.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_setup.Tpo $(DEPDIR)/pcem-vid_voodoo_setup.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_setup.c' object='pcem-vid_voodoo_setup.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_setup.o `test -f 'vid_voodoo_setup.c' || echo '$(srcdir)/'`vid_voodoo_setup.c
+
+pcem-vid_voodoo_setup.obj: vid_voodoo_setup.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_setup.obj -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_setup.Tpo -c -o pcem-vid_voodoo_setup.obj `if test -f 'vid_voodoo_setup.c'; then $(CYGPATH_W) 'vid_voodoo_setup.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_setup.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_setup.Tpo $(DEPDIR)/pcem-vid_voodoo_setup.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_setup.c' object='pcem-vid_voodoo_setup.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_setup.obj `if test -f 'vid_voodoo_setup.c'; then $(CYGPATH_W) 'vid_voodoo_setup.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_setup.c'; fi`
+
+pcem-vid_voodoo_texture.o: vid_voodoo_texture.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_texture.o -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_texture.Tpo -c -o pcem-vid_voodoo_texture.o `test -f 'vid_voodoo_texture.c' || echo '$(srcdir)/'`vid_voodoo_texture.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_texture.Tpo $(DEPDIR)/pcem-vid_voodoo_texture.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_texture.c' object='pcem-vid_voodoo_texture.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_texture.o `test -f 'vid_voodoo_texture.c' || echo '$(srcdir)/'`vid_voodoo_texture.c
+
+pcem-vid_voodoo_texture.obj: vid_voodoo_texture.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vid_voodoo_texture.obj -MD -MP -MF $(DEPDIR)/pcem-vid_voodoo_texture.Tpo -c -o pcem-vid_voodoo_texture.obj `if test -f 'vid_voodoo_texture.c'; then $(CYGPATH_W) 'vid_voodoo_texture.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_texture.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vid_voodoo_texture.Tpo $(DEPDIR)/pcem-vid_voodoo_texture.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vid_voodoo_texture.c' object='pcem-vid_voodoo_texture.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_voodoo_texture.obj `if test -f 'vid_voodoo_texture.c'; then $(CYGPATH_W) 'vid_voodoo_texture.c'; else $(CYGPATH_W) '$(srcdir)/vid_voodoo_texture.c'; fi`
+
pcem-video.o: video.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-video.o -MD -MP -MF $(DEPDIR)/pcem-video.Tpo -c -o pcem-video.o `test -f 'video.c' || echo '$(srcdir)/'`video.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-video.Tpo $(DEPDIR)/pcem-video.Po
@@ -3819,6 +5046,62 @@ pcem-vid_wy700.obj: vid_wy700.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vid_wy700.obj `if test -f 'vid_wy700.c'; then $(CYGPATH_W) 'vid_wy700.c'; else $(CYGPATH_W) '$(srcdir)/vid_wy700.c'; fi`
+pcem-vt82c586b.o: vt82c586b.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vt82c586b.o -MD -MP -MF $(DEPDIR)/pcem-vt82c586b.Tpo -c -o pcem-vt82c586b.o `test -f 'vt82c586b.c' || echo '$(srcdir)/'`vt82c586b.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vt82c586b.Tpo $(DEPDIR)/pcem-vt82c586b.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vt82c586b.c' object='pcem-vt82c586b.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vt82c586b.o `test -f 'vt82c586b.c' || echo '$(srcdir)/'`vt82c586b.c
+
+pcem-vt82c586b.obj: vt82c586b.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vt82c586b.obj -MD -MP -MF $(DEPDIR)/pcem-vt82c586b.Tpo -c -o pcem-vt82c586b.obj `if test -f 'vt82c586b.c'; then $(CYGPATH_W) 'vt82c586b.c'; else $(CYGPATH_W) '$(srcdir)/vt82c586b.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vt82c586b.Tpo $(DEPDIR)/pcem-vt82c586b.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vt82c586b.c' object='pcem-vt82c586b.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vt82c586b.obj `if test -f 'vt82c586b.c'; then $(CYGPATH_W) 'vt82c586b.c'; else $(CYGPATH_W) '$(srcdir)/vt82c586b.c'; fi`
+
+pcem-vl82c480.o: vl82c480.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vl82c480.o -MD -MP -MF $(DEPDIR)/pcem-vl82c480.Tpo -c -o pcem-vl82c480.o `test -f 'vl82c480.c' || echo '$(srcdir)/'`vl82c480.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vl82c480.Tpo $(DEPDIR)/pcem-vl82c480.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vl82c480.c' object='pcem-vl82c480.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vl82c480.o `test -f 'vl82c480.c' || echo '$(srcdir)/'`vl82c480.c
+
+pcem-vl82c480.obj: vl82c480.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-vl82c480.obj -MD -MP -MF $(DEPDIR)/pcem-vl82c480.Tpo -c -o pcem-vl82c480.obj `if test -f 'vl82c480.c'; then $(CYGPATH_W) 'vl82c480.c'; else $(CYGPATH_W) '$(srcdir)/vl82c480.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-vl82c480.Tpo $(DEPDIR)/pcem-vl82c480.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='vl82c480.c' object='pcem-vl82c480.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-vl82c480.obj `if test -f 'vl82c480.c'; then $(CYGPATH_W) 'vl82c480.c'; else $(CYGPATH_W) '$(srcdir)/vl82c480.c'; fi`
+
+pcem-w83877tf.o: w83877tf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-w83877tf.o -MD -MP -MF $(DEPDIR)/pcem-w83877tf.Tpo -c -o pcem-w83877tf.o `test -f 'w83877tf.c' || echo '$(srcdir)/'`w83877tf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-w83877tf.Tpo $(DEPDIR)/pcem-w83877tf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='w83877tf.c' object='pcem-w83877tf.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-w83877tf.o `test -f 'w83877tf.c' || echo '$(srcdir)/'`w83877tf.c
+
+pcem-w83877tf.obj: w83877tf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-w83877tf.obj -MD -MP -MF $(DEPDIR)/pcem-w83877tf.Tpo -c -o pcem-w83877tf.obj `if test -f 'w83877tf.c'; then $(CYGPATH_W) 'w83877tf.c'; else $(CYGPATH_W) '$(srcdir)/w83877tf.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-w83877tf.Tpo $(DEPDIR)/pcem-w83877tf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='w83877tf.c' object='pcem-w83877tf.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-w83877tf.obj `if test -f 'w83877tf.c'; then $(CYGPATH_W) 'w83877tf.c'; else $(CYGPATH_W) '$(srcdir)/w83877tf.c'; fi`
+
+pcem-w83977tf.o: w83977tf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-w83977tf.o -MD -MP -MF $(DEPDIR)/pcem-w83977tf.Tpo -c -o pcem-w83977tf.o `test -f 'w83977tf.c' || echo '$(srcdir)/'`w83977tf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-w83977tf.Tpo $(DEPDIR)/pcem-w83977tf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='w83977tf.c' object='pcem-w83977tf.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-w83977tf.o `test -f 'w83977tf.c' || echo '$(srcdir)/'`w83977tf.c
+
+pcem-w83977tf.obj: w83977tf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-w83977tf.obj -MD -MP -MF $(DEPDIR)/pcem-w83977tf.Tpo -c -o pcem-w83977tf.obj `if test -f 'w83977tf.c'; then $(CYGPATH_W) 'w83977tf.c'; else $(CYGPATH_W) '$(srcdir)/w83977tf.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-w83977tf.Tpo $(DEPDIR)/pcem-w83977tf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='w83977tf.c' object='pcem-w83977tf.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-w83977tf.obj `if test -f 'w83977tf.c'; then $(CYGPATH_W) 'w83977tf.c'; else $(CYGPATH_W) '$(srcdir)/w83977tf.c'; fi`
+
pcem-x86seg.o: x86seg.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-x86seg.o -MD -MP -MF $(DEPDIR)/pcem-x86seg.Tpo -c -o pcem-x86seg.o `test -f 'x86seg.c' || echo '$(srcdir)/'`x86seg.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-x86seg.Tpo $(DEPDIR)/pcem-x86seg.Po
@@ -3847,6 +5130,20 @@ pcem-x87.obj: x87.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-x87.obj `if test -f 'x87.c'; then $(CYGPATH_W) 'x87.c'; else $(CYGPATH_W) '$(srcdir)/x87.c'; fi`
+pcem-x87_timings.o: x87_timings.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-x87_timings.o -MD -MP -MF $(DEPDIR)/pcem-x87_timings.Tpo -c -o pcem-x87_timings.o `test -f 'x87_timings.c' || echo '$(srcdir)/'`x87_timings.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-x87_timings.Tpo $(DEPDIR)/pcem-x87_timings.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='x87_timings.c' object='pcem-x87_timings.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-x87_timings.o `test -f 'x87_timings.c' || echo '$(srcdir)/'`x87_timings.c
+
+pcem-x87_timings.obj: x87_timings.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-x87_timings.obj -MD -MP -MF $(DEPDIR)/pcem-x87_timings.Tpo -c -o pcem-x87_timings.obj `if test -f 'x87_timings.c'; then $(CYGPATH_W) 'x87_timings.c'; else $(CYGPATH_W) '$(srcdir)/x87_timings.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-x87_timings.Tpo $(DEPDIR)/pcem-x87_timings.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='x87_timings.c' object='pcem-x87_timings.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-x87_timings.obj `if test -f 'x87_timings.c'; then $(CYGPATH_W) 'x87_timings.c'; else $(CYGPATH_W) '$(srcdir)/x87_timings.c'; fi`
+
pcem-xi8088.o: xi8088.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-xi8088.o -MD -MP -MF $(DEPDIR)/pcem-xi8088.Tpo -c -o pcem-xi8088.o `test -f 'xi8088.c' || echo '$(srcdir)/'`xi8088.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-xi8088.Tpo $(DEPDIR)/pcem-xi8088.Po
@@ -3889,6 +5186,118 @@ dosbox/pcem-vid_cga_comp.obj: dosbox/vid_cga_comp.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o dosbox/pcem-vid_cga_comp.obj `if test -f 'dosbox/vid_cga_comp.c'; then $(CYGPATH_W) 'dosbox/vid_cga_comp.c'; else $(CYGPATH_W) '$(srcdir)/dosbox/vid_cga_comp.c'; fi`
+minivhd/pcem-cwalk.o: minivhd/cwalk.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-cwalk.o -MD -MP -MF minivhd/$(DEPDIR)/pcem-cwalk.Tpo -c -o minivhd/pcem-cwalk.o `test -f 'minivhd/cwalk.c' || echo '$(srcdir)/'`minivhd/cwalk.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-cwalk.Tpo minivhd/$(DEPDIR)/pcem-cwalk.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/cwalk.c' object='minivhd/pcem-cwalk.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-cwalk.o `test -f 'minivhd/cwalk.c' || echo '$(srcdir)/'`minivhd/cwalk.c
+
+minivhd/pcem-cwalk.obj: minivhd/cwalk.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-cwalk.obj -MD -MP -MF minivhd/$(DEPDIR)/pcem-cwalk.Tpo -c -o minivhd/pcem-cwalk.obj `if test -f 'minivhd/cwalk.c'; then $(CYGPATH_W) 'minivhd/cwalk.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/cwalk.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-cwalk.Tpo minivhd/$(DEPDIR)/pcem-cwalk.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/cwalk.c' object='minivhd/pcem-cwalk.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-cwalk.obj `if test -f 'minivhd/cwalk.c'; then $(CYGPATH_W) 'minivhd/cwalk.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/cwalk.c'; fi`
+
+minivhd/pcem-libxml2_encoding.o: minivhd/libxml2_encoding.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-libxml2_encoding.o -MD -MP -MF minivhd/$(DEPDIR)/pcem-libxml2_encoding.Tpo -c -o minivhd/pcem-libxml2_encoding.o `test -f 'minivhd/libxml2_encoding.c' || echo '$(srcdir)/'`minivhd/libxml2_encoding.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-libxml2_encoding.Tpo minivhd/$(DEPDIR)/pcem-libxml2_encoding.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/libxml2_encoding.c' object='minivhd/pcem-libxml2_encoding.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-libxml2_encoding.o `test -f 'minivhd/libxml2_encoding.c' || echo '$(srcdir)/'`minivhd/libxml2_encoding.c
+
+minivhd/pcem-libxml2_encoding.obj: minivhd/libxml2_encoding.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-libxml2_encoding.obj -MD -MP -MF minivhd/$(DEPDIR)/pcem-libxml2_encoding.Tpo -c -o minivhd/pcem-libxml2_encoding.obj `if test -f 'minivhd/libxml2_encoding.c'; then $(CYGPATH_W) 'minivhd/libxml2_encoding.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/libxml2_encoding.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-libxml2_encoding.Tpo minivhd/$(DEPDIR)/pcem-libxml2_encoding.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/libxml2_encoding.c' object='minivhd/pcem-libxml2_encoding.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-libxml2_encoding.obj `if test -f 'minivhd/libxml2_encoding.c'; then $(CYGPATH_W) 'minivhd/libxml2_encoding.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/libxml2_encoding.c'; fi`
+
+minivhd/pcem-minivhd_convert.o: minivhd/minivhd_convert.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-minivhd_convert.o -MD -MP -MF minivhd/$(DEPDIR)/pcem-minivhd_convert.Tpo -c -o minivhd/pcem-minivhd_convert.o `test -f 'minivhd/minivhd_convert.c' || echo '$(srcdir)/'`minivhd/minivhd_convert.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-minivhd_convert.Tpo minivhd/$(DEPDIR)/pcem-minivhd_convert.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/minivhd_convert.c' object='minivhd/pcem-minivhd_convert.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-minivhd_convert.o `test -f 'minivhd/minivhd_convert.c' || echo '$(srcdir)/'`minivhd/minivhd_convert.c
+
+minivhd/pcem-minivhd_convert.obj: minivhd/minivhd_convert.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-minivhd_convert.obj -MD -MP -MF minivhd/$(DEPDIR)/pcem-minivhd_convert.Tpo -c -o minivhd/pcem-minivhd_convert.obj `if test -f 'minivhd/minivhd_convert.c'; then $(CYGPATH_W) 'minivhd/minivhd_convert.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/minivhd_convert.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-minivhd_convert.Tpo minivhd/$(DEPDIR)/pcem-minivhd_convert.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/minivhd_convert.c' object='minivhd/pcem-minivhd_convert.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-minivhd_convert.obj `if test -f 'minivhd/minivhd_convert.c'; then $(CYGPATH_W) 'minivhd/minivhd_convert.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/minivhd_convert.c'; fi`
+
+minivhd/pcem-minivhd_create.o: minivhd/minivhd_create.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-minivhd_create.o -MD -MP -MF minivhd/$(DEPDIR)/pcem-minivhd_create.Tpo -c -o minivhd/pcem-minivhd_create.o `test -f 'minivhd/minivhd_create.c' || echo '$(srcdir)/'`minivhd/minivhd_create.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-minivhd_create.Tpo minivhd/$(DEPDIR)/pcem-minivhd_create.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/minivhd_create.c' object='minivhd/pcem-minivhd_create.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-minivhd_create.o `test -f 'minivhd/minivhd_create.c' || echo '$(srcdir)/'`minivhd/minivhd_create.c
+
+minivhd/pcem-minivhd_create.obj: minivhd/minivhd_create.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-minivhd_create.obj -MD -MP -MF minivhd/$(DEPDIR)/pcem-minivhd_create.Tpo -c -o minivhd/pcem-minivhd_create.obj `if test -f 'minivhd/minivhd_create.c'; then $(CYGPATH_W) 'minivhd/minivhd_create.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/minivhd_create.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-minivhd_create.Tpo minivhd/$(DEPDIR)/pcem-minivhd_create.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/minivhd_create.c' object='minivhd/pcem-minivhd_create.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-minivhd_create.obj `if test -f 'minivhd/minivhd_create.c'; then $(CYGPATH_W) 'minivhd/minivhd_create.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/minivhd_create.c'; fi`
+
+minivhd/pcem-minivhd_io.o: minivhd/minivhd_io.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-minivhd_io.o -MD -MP -MF minivhd/$(DEPDIR)/pcem-minivhd_io.Tpo -c -o minivhd/pcem-minivhd_io.o `test -f 'minivhd/minivhd_io.c' || echo '$(srcdir)/'`minivhd/minivhd_io.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-minivhd_io.Tpo minivhd/$(DEPDIR)/pcem-minivhd_io.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/minivhd_io.c' object='minivhd/pcem-minivhd_io.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-minivhd_io.o `test -f 'minivhd/minivhd_io.c' || echo '$(srcdir)/'`minivhd/minivhd_io.c
+
+minivhd/pcem-minivhd_io.obj: minivhd/minivhd_io.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-minivhd_io.obj -MD -MP -MF minivhd/$(DEPDIR)/pcem-minivhd_io.Tpo -c -o minivhd/pcem-minivhd_io.obj `if test -f 'minivhd/minivhd_io.c'; then $(CYGPATH_W) 'minivhd/minivhd_io.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/minivhd_io.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-minivhd_io.Tpo minivhd/$(DEPDIR)/pcem-minivhd_io.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/minivhd_io.c' object='minivhd/pcem-minivhd_io.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-minivhd_io.obj `if test -f 'minivhd/minivhd_io.c'; then $(CYGPATH_W) 'minivhd/minivhd_io.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/minivhd_io.c'; fi`
+
+minivhd/pcem-minivhd_manage.o: minivhd/minivhd_manage.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-minivhd_manage.o -MD -MP -MF minivhd/$(DEPDIR)/pcem-minivhd_manage.Tpo -c -o minivhd/pcem-minivhd_manage.o `test -f 'minivhd/minivhd_manage.c' || echo '$(srcdir)/'`minivhd/minivhd_manage.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-minivhd_manage.Tpo minivhd/$(DEPDIR)/pcem-minivhd_manage.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/minivhd_manage.c' object='minivhd/pcem-minivhd_manage.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-minivhd_manage.o `test -f 'minivhd/minivhd_manage.c' || echo '$(srcdir)/'`minivhd/minivhd_manage.c
+
+minivhd/pcem-minivhd_manage.obj: minivhd/minivhd_manage.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-minivhd_manage.obj -MD -MP -MF minivhd/$(DEPDIR)/pcem-minivhd_manage.Tpo -c -o minivhd/pcem-minivhd_manage.obj `if test -f 'minivhd/minivhd_manage.c'; then $(CYGPATH_W) 'minivhd/minivhd_manage.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/minivhd_manage.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-minivhd_manage.Tpo minivhd/$(DEPDIR)/pcem-minivhd_manage.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/minivhd_manage.c' object='minivhd/pcem-minivhd_manage.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-minivhd_manage.obj `if test -f 'minivhd/minivhd_manage.c'; then $(CYGPATH_W) 'minivhd/minivhd_manage.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/minivhd_manage.c'; fi`
+
+minivhd/pcem-minivhd_struct_rw.o: minivhd/minivhd_struct_rw.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-minivhd_struct_rw.o -MD -MP -MF minivhd/$(DEPDIR)/pcem-minivhd_struct_rw.Tpo -c -o minivhd/pcem-minivhd_struct_rw.o `test -f 'minivhd/minivhd_struct_rw.c' || echo '$(srcdir)/'`minivhd/minivhd_struct_rw.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-minivhd_struct_rw.Tpo minivhd/$(DEPDIR)/pcem-minivhd_struct_rw.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/minivhd_struct_rw.c' object='minivhd/pcem-minivhd_struct_rw.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-minivhd_struct_rw.o `test -f 'minivhd/minivhd_struct_rw.c' || echo '$(srcdir)/'`minivhd/minivhd_struct_rw.c
+
+minivhd/pcem-minivhd_struct_rw.obj: minivhd/minivhd_struct_rw.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-minivhd_struct_rw.obj -MD -MP -MF minivhd/$(DEPDIR)/pcem-minivhd_struct_rw.Tpo -c -o minivhd/pcem-minivhd_struct_rw.obj `if test -f 'minivhd/minivhd_struct_rw.c'; then $(CYGPATH_W) 'minivhd/minivhd_struct_rw.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/minivhd_struct_rw.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-minivhd_struct_rw.Tpo minivhd/$(DEPDIR)/pcem-minivhd_struct_rw.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/minivhd_struct_rw.c' object='minivhd/pcem-minivhd_struct_rw.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-minivhd_struct_rw.obj `if test -f 'minivhd/minivhd_struct_rw.c'; then $(CYGPATH_W) 'minivhd/minivhd_struct_rw.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/minivhd_struct_rw.c'; fi`
+
+minivhd/pcem-minivhd_util.o: minivhd/minivhd_util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-minivhd_util.o -MD -MP -MF minivhd/$(DEPDIR)/pcem-minivhd_util.Tpo -c -o minivhd/pcem-minivhd_util.o `test -f 'minivhd/minivhd_util.c' || echo '$(srcdir)/'`minivhd/minivhd_util.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-minivhd_util.Tpo minivhd/$(DEPDIR)/pcem-minivhd_util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/minivhd_util.c' object='minivhd/pcem-minivhd_util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-minivhd_util.o `test -f 'minivhd/minivhd_util.c' || echo '$(srcdir)/'`minivhd/minivhd_util.c
+
+minivhd/pcem-minivhd_util.obj: minivhd/minivhd_util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT minivhd/pcem-minivhd_util.obj -MD -MP -MF minivhd/$(DEPDIR)/pcem-minivhd_util.Tpo -c -o minivhd/pcem-minivhd_util.obj `if test -f 'minivhd/minivhd_util.c'; then $(CYGPATH_W) 'minivhd/minivhd_util.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/minivhd_util.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) minivhd/$(DEPDIR)/pcem-minivhd_util.Tpo minivhd/$(DEPDIR)/pcem-minivhd_util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='minivhd/minivhd_util.c' object='minivhd/pcem-minivhd_util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o minivhd/pcem-minivhd_util.obj `if test -f 'minivhd/minivhd_util.c'; then $(CYGPATH_W) 'minivhd/minivhd_util.c'; else $(CYGPATH_W) '$(srcdir)/minivhd/minivhd_util.c'; fi`
+
pcem-wx-config_sel.o: wx-config_sel.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-wx-config_sel.o -MD -MP -MF $(DEPDIR)/pcem-wx-config_sel.Tpo -c -o pcem-wx-config_sel.o `test -f 'wx-config_sel.c' || echo '$(srcdir)/'`wx-config_sel.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-wx-config_sel.Tpo $(DEPDIR)/pcem-wx-config_sel.Po
@@ -4127,6 +5536,48 @@ pcem-codegen_backend_x86.obj: codegen_backend_x86.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86.obj `if test -f 'codegen_backend_x86.c'; then $(CYGPATH_W) 'codegen_backend_x86.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86.c'; fi`
+pcem-codegen_backend_x86_ops.o: codegen_backend_x86_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86_ops.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86_ops.Tpo -c -o pcem-codegen_backend_x86_ops.o `test -f 'codegen_backend_x86_ops.c' || echo '$(srcdir)/'`codegen_backend_x86_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86_ops.Tpo $(DEPDIR)/pcem-codegen_backend_x86_ops.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86_ops.c' object='pcem-codegen_backend_x86_ops.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86_ops.o `test -f 'codegen_backend_x86_ops.c' || echo '$(srcdir)/'`codegen_backend_x86_ops.c
+
+pcem-codegen_backend_x86_ops.obj: codegen_backend_x86_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86_ops.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86_ops.Tpo -c -o pcem-codegen_backend_x86_ops.obj `if test -f 'codegen_backend_x86_ops.c'; then $(CYGPATH_W) 'codegen_backend_x86_ops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86_ops.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86_ops.Tpo $(DEPDIR)/pcem-codegen_backend_x86_ops.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86_ops.c' object='pcem-codegen_backend_x86_ops.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86_ops.obj `if test -f 'codegen_backend_x86_ops.c'; then $(CYGPATH_W) 'codegen_backend_x86_ops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86_ops.c'; fi`
+
+pcem-codegen_backend_x86_ops_fpu.o: codegen_backend_x86_ops_fpu.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86_ops_fpu.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86_ops_fpu.Tpo -c -o pcem-codegen_backend_x86_ops_fpu.o `test -f 'codegen_backend_x86_ops_fpu.c' || echo '$(srcdir)/'`codegen_backend_x86_ops_fpu.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86_ops_fpu.Tpo $(DEPDIR)/pcem-codegen_backend_x86_ops_fpu.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86_ops_fpu.c' object='pcem-codegen_backend_x86_ops_fpu.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86_ops_fpu.o `test -f 'codegen_backend_x86_ops_fpu.c' || echo '$(srcdir)/'`codegen_backend_x86_ops_fpu.c
+
+pcem-codegen_backend_x86_ops_fpu.obj: codegen_backend_x86_ops_fpu.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86_ops_fpu.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86_ops_fpu.Tpo -c -o pcem-codegen_backend_x86_ops_fpu.obj `if test -f 'codegen_backend_x86_ops_fpu.c'; then $(CYGPATH_W) 'codegen_backend_x86_ops_fpu.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86_ops_fpu.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86_ops_fpu.Tpo $(DEPDIR)/pcem-codegen_backend_x86_ops_fpu.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86_ops_fpu.c' object='pcem-codegen_backend_x86_ops_fpu.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86_ops_fpu.obj `if test -f 'codegen_backend_x86_ops_fpu.c'; then $(CYGPATH_W) 'codegen_backend_x86_ops_fpu.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86_ops_fpu.c'; fi`
+
+pcem-codegen_backend_x86_ops_sse.o: codegen_backend_x86_ops_sse.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86_ops_sse.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86_ops_sse.Tpo -c -o pcem-codegen_backend_x86_ops_sse.o `test -f 'codegen_backend_x86_ops_sse.c' || echo '$(srcdir)/'`codegen_backend_x86_ops_sse.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86_ops_sse.Tpo $(DEPDIR)/pcem-codegen_backend_x86_ops_sse.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86_ops_sse.c' object='pcem-codegen_backend_x86_ops_sse.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86_ops_sse.o `test -f 'codegen_backend_x86_ops_sse.c' || echo '$(srcdir)/'`codegen_backend_x86_ops_sse.c
+
+pcem-codegen_backend_x86_ops_sse.obj: codegen_backend_x86_ops_sse.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86_ops_sse.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86_ops_sse.Tpo -c -o pcem-codegen_backend_x86_ops_sse.obj `if test -f 'codegen_backend_x86_ops_sse.c'; then $(CYGPATH_W) 'codegen_backend_x86_ops_sse.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86_ops_sse.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86_ops_sse.Tpo $(DEPDIR)/pcem-codegen_backend_x86_ops_sse.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86_ops_sse.c' object='pcem-codegen_backend_x86_ops_sse.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86_ops_sse.obj `if test -f 'codegen_backend_x86_ops_sse.c'; then $(CYGPATH_W) 'codegen_backend_x86_ops_sse.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86_ops_sse.c'; fi`
+
pcem-codegen_backend_x86_uops.o: codegen_backend_x86_uops.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86_uops.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86_uops.Tpo -c -o pcem-codegen_backend_x86_uops.o `test -f 'codegen_backend_x86_uops.c' || echo '$(srcdir)/'`codegen_backend_x86_uops.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86_uops.Tpo $(DEPDIR)/pcem-codegen_backend_x86_uops.Po
@@ -4155,6 +5606,34 @@ pcem-codegen_backend_x86-64.obj: codegen_backend_x86-64.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86-64.obj `if test -f 'codegen_backend_x86-64.c'; then $(CYGPATH_W) 'codegen_backend_x86-64.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86-64.c'; fi`
+pcem-codegen_backend_x86-64_ops.o: codegen_backend_x86-64_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86-64_ops.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86-64_ops.Tpo -c -o pcem-codegen_backend_x86-64_ops.o `test -f 'codegen_backend_x86-64_ops.c' || echo '$(srcdir)/'`codegen_backend_x86-64_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86-64_ops.Tpo $(DEPDIR)/pcem-codegen_backend_x86-64_ops.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86-64_ops.c' object='pcem-codegen_backend_x86-64_ops.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86-64_ops.o `test -f 'codegen_backend_x86-64_ops.c' || echo '$(srcdir)/'`codegen_backend_x86-64_ops.c
+
+pcem-codegen_backend_x86-64_ops.obj: codegen_backend_x86-64_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86-64_ops.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86-64_ops.Tpo -c -o pcem-codegen_backend_x86-64_ops.obj `if test -f 'codegen_backend_x86-64_ops.c'; then $(CYGPATH_W) 'codegen_backend_x86-64_ops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86-64_ops.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86-64_ops.Tpo $(DEPDIR)/pcem-codegen_backend_x86-64_ops.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86-64_ops.c' object='pcem-codegen_backend_x86-64_ops.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86-64_ops.obj `if test -f 'codegen_backend_x86-64_ops.c'; then $(CYGPATH_W) 'codegen_backend_x86-64_ops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86-64_ops.c'; fi`
+
+pcem-codegen_backend_x86-64_ops_sse.o: codegen_backend_x86-64_ops_sse.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86-64_ops_sse.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86-64_ops_sse.Tpo -c -o pcem-codegen_backend_x86-64_ops_sse.o `test -f 'codegen_backend_x86-64_ops_sse.c' || echo '$(srcdir)/'`codegen_backend_x86-64_ops_sse.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86-64_ops_sse.Tpo $(DEPDIR)/pcem-codegen_backend_x86-64_ops_sse.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86-64_ops_sse.c' object='pcem-codegen_backend_x86-64_ops_sse.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86-64_ops_sse.o `test -f 'codegen_backend_x86-64_ops_sse.c' || echo '$(srcdir)/'`codegen_backend_x86-64_ops_sse.c
+
+pcem-codegen_backend_x86-64_ops_sse.obj: codegen_backend_x86-64_ops_sse.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86-64_ops_sse.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86-64_ops_sse.Tpo -c -o pcem-codegen_backend_x86-64_ops_sse.obj `if test -f 'codegen_backend_x86-64_ops_sse.c'; then $(CYGPATH_W) 'codegen_backend_x86-64_ops_sse.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86-64_ops_sse.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86-64_ops_sse.Tpo $(DEPDIR)/pcem-codegen_backend_x86-64_ops_sse.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_x86-64_ops_sse.c' object='pcem-codegen_backend_x86-64_ops_sse.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_x86-64_ops_sse.obj `if test -f 'codegen_backend_x86-64_ops_sse.c'; then $(CYGPATH_W) 'codegen_backend_x86-64_ops_sse.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_x86-64_ops_sse.c'; fi`
+
pcem-codegen_backend_x86-64_uops.o: codegen_backend_x86-64_uops.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_x86-64_uops.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_x86-64_uops.Tpo -c -o pcem-codegen_backend_x86-64_uops.o `test -f 'codegen_backend_x86-64_uops.c' || echo '$(srcdir)/'`codegen_backend_x86-64_uops.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_x86-64_uops.Tpo $(DEPDIR)/pcem-codegen_backend_x86-64_uops.Po
@@ -4183,6 +5662,20 @@ pcem-codegen_backend_arm.obj: codegen_backend_arm.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm.obj `if test -f 'codegen_backend_arm.c'; then $(CYGPATH_W) 'codegen_backend_arm.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm.c'; fi`
+pcem-codegen_backend_arm_ops.o: codegen_backend_arm_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm_ops.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm_ops.Tpo -c -o pcem-codegen_backend_arm_ops.o `test -f 'codegen_backend_arm_ops.c' || echo '$(srcdir)/'`codegen_backend_arm_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm_ops.Tpo $(DEPDIR)/pcem-codegen_backend_arm_ops.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_arm_ops.c' object='pcem-codegen_backend_arm_ops.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm_ops.o `test -f 'codegen_backend_arm_ops.c' || echo '$(srcdir)/'`codegen_backend_arm_ops.c
+
+pcem-codegen_backend_arm_ops.obj: codegen_backend_arm_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm_ops.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm_ops.Tpo -c -o pcem-codegen_backend_arm_ops.obj `if test -f 'codegen_backend_arm_ops.c'; then $(CYGPATH_W) 'codegen_backend_arm_ops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm_ops.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm_ops.Tpo $(DEPDIR)/pcem-codegen_backend_arm_ops.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_arm_ops.c' object='pcem-codegen_backend_arm_ops.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm_ops.obj `if test -f 'codegen_backend_arm_ops.c'; then $(CYGPATH_W) 'codegen_backend_arm_ops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm_ops.c'; fi`
+
pcem-codegen_backend_arm_uops.o: codegen_backend_arm_uops.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm_uops.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm_uops.Tpo -c -o pcem-codegen_backend_arm_uops.o `test -f 'codegen_backend_arm_uops.c' || echo '$(srcdir)/'`codegen_backend_arm_uops.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm_uops.Tpo $(DEPDIR)/pcem-codegen_backend_arm_uops.Po
@@ -4211,6 +5704,34 @@ pcem-codegen_backend_arm64.obj: codegen_backend_arm64.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm64.obj `if test -f 'codegen_backend_arm64.c'; then $(CYGPATH_W) 'codegen_backend_arm64.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm64.c'; fi`
+pcem-codegen_backend_arm64_imm.o: codegen_backend_arm64_imm.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm64_imm.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm64_imm.Tpo -c -o pcem-codegen_backend_arm64_imm.o `test -f 'codegen_backend_arm64_imm.c' || echo '$(srcdir)/'`codegen_backend_arm64_imm.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm64_imm.Tpo $(DEPDIR)/pcem-codegen_backend_arm64_imm.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_arm64_imm.c' object='pcem-codegen_backend_arm64_imm.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm64_imm.o `test -f 'codegen_backend_arm64_imm.c' || echo '$(srcdir)/'`codegen_backend_arm64_imm.c
+
+pcem-codegen_backend_arm64_imm.obj: codegen_backend_arm64_imm.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm64_imm.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm64_imm.Tpo -c -o pcem-codegen_backend_arm64_imm.obj `if test -f 'codegen_backend_arm64_imm.c'; then $(CYGPATH_W) 'codegen_backend_arm64_imm.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm64_imm.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm64_imm.Tpo $(DEPDIR)/pcem-codegen_backend_arm64_imm.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_arm64_imm.c' object='pcem-codegen_backend_arm64_imm.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm64_imm.obj `if test -f 'codegen_backend_arm64_imm.c'; then $(CYGPATH_W) 'codegen_backend_arm64_imm.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm64_imm.c'; fi`
+
+pcem-codegen_backend_arm64_ops.o: codegen_backend_arm64_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm64_ops.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm64_ops.Tpo -c -o pcem-codegen_backend_arm64_ops.o `test -f 'codegen_backend_arm64_ops.c' || echo '$(srcdir)/'`codegen_backend_arm64_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm64_ops.Tpo $(DEPDIR)/pcem-codegen_backend_arm64_ops.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_arm64_ops.c' object='pcem-codegen_backend_arm64_ops.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm64_ops.o `test -f 'codegen_backend_arm64_ops.c' || echo '$(srcdir)/'`codegen_backend_arm64_ops.c
+
+pcem-codegen_backend_arm64_ops.obj: codegen_backend_arm64_ops.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm64_ops.obj -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm64_ops.Tpo -c -o pcem-codegen_backend_arm64_ops.obj `if test -f 'codegen_backend_arm64_ops.c'; then $(CYGPATH_W) 'codegen_backend_arm64_ops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm64_ops.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm64_ops.Tpo $(DEPDIR)/pcem-codegen_backend_arm64_ops.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='codegen_backend_arm64_ops.c' object='pcem-codegen_backend_arm64_ops.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -c -o pcem-codegen_backend_arm64_ops.obj `if test -f 'codegen_backend_arm64_ops.c'; then $(CYGPATH_W) 'codegen_backend_arm64_ops.c'; else $(CYGPATH_W) '$(srcdir)/codegen_backend_arm64_ops.c'; fi`
+
pcem-codegen_backend_arm64_uops.o: codegen_backend_arm64_uops.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcem_CFLAGS) $(CFLAGS) -MT pcem-codegen_backend_arm64_uops.o -MD -MP -MF $(DEPDIR)/pcem-codegen_backend_arm64_uops.Tpo -c -o pcem-codegen_backend_arm64_uops.o `test -f 'codegen_backend_arm64_uops.c' || echo '$(srcdir)/'`codegen_backend_arm64_uops.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pcem-codegen_backend_arm64_uops.Tpo $(DEPDIR)/pcem-codegen_backend_arm64_uops.Po
@@ -5232,6 +6753,8 @@ distclean-generic:
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-rm -f dosbox/$(DEPDIR)/$(am__dirstamp)
-rm -f dosbox/$(am__dirstamp)
+ -rm -f minivhd/$(DEPDIR)/$(am__dirstamp)
+ -rm -f minivhd/$(am__dirstamp)
-rm -f resid-fp/$(DEPDIR)/$(am__dirstamp)
-rm -f resid-fp/$(am__dirstamp)
-rm -f slirp/$(DEPDIR)/$(am__dirstamp)
@@ -5246,13 +6769,18 @@ clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
distclean: distclean-am
-rm -f ./$(DEPDIR)/pcem-386.Po
+ -rm -f ./$(DEPDIR)/pcem-386_common.Po
-rm -f ./$(DEPDIR)/pcem-386_dynarec.Po
-rm -f ./$(DEPDIR)/pcem-386_dynarec_ops.Po
-rm -f ./$(DEPDIR)/pcem-808x.Po
+ -rm -f ./$(DEPDIR)/pcem-82091aa.Po
-rm -f ./$(DEPDIR)/pcem-acc2036.Po
+ -rm -f ./$(DEPDIR)/pcem-acc2168.Po
+ -rm -f ./$(DEPDIR)/pcem-acc3221.Po
-rm -f ./$(DEPDIR)/pcem-acer386sx.Po
-rm -f ./$(DEPDIR)/pcem-ali1429.Po
-rm -f ./$(DEPDIR)/pcem-amstrad.Po
+ -rm -f ./$(DEPDIR)/pcem-cassette.Po
-rm -f ./$(DEPDIR)/pcem-cbm_io.Po
-rm -f ./$(DEPDIR)/pcem-cdrom-image.Po
-rm -f ./$(DEPDIR)/pcem-cdrom-ioctl-dummy.Po
@@ -5262,24 +6790,62 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/pcem-cdrom-null.Po
-rm -f ./$(DEPDIR)/pcem-cmd640.Po
-rm -f ./$(DEPDIR)/pcem-codegen.Po
- -rm -f ./$(DEPDIR)/pcem-codegen_backend.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_accumulate.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_allocator.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_arm.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_arm64.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_arm64_imm.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_arm64_ops.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_arm64_uops.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_arm_ops.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_arm_uops.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_x86-64.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86-64_ops.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86-64_ops_sse.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_x86-64_uops.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_x86.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86_ops.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86_ops_fpu.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86_ops_sse.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_x86_uops.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_block.Po
-rm -f ./$(DEPDIR)/pcem-codegen_ir.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_3dnow.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_arith.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_branch.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_fpu_arith.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_fpu_constant.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_fpu_loadstore.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_fpu_misc.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_helpers.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_jump.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_logic.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_misc.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_mmx_arith.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_mmx_cmp.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_mmx_loadstore.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_mmx_logic.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_mmx_pack.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_mmx_shift.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_mov.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_shift.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_stack.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_reg.Po
-rm -f ./$(DEPDIR)/pcem-codegen_timing_486.Po
-rm -f ./$(DEPDIR)/pcem-codegen_timing_686.Po
-rm -f ./$(DEPDIR)/pcem-codegen_timing_common.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_timing_cyrixiii.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_timing_k6.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_timing_p6.Po
-rm -f ./$(DEPDIR)/pcem-codegen_timing_pentium.Po
-rm -f ./$(DEPDIR)/pcem-codegen_timing_winchip.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_timing_winchip2.Po
-rm -f ./$(DEPDIR)/pcem-compaq.Po
-rm -f ./$(DEPDIR)/pcem-config.Po
-rm -f ./$(DEPDIR)/pcem-cpu.Po
+ -rm -f ./$(DEPDIR)/pcem-cpu_tables.Po
+ -rm -f ./$(DEPDIR)/pcem-cs8230.Po
-rm -f ./$(DEPDIR)/pcem-dells200.Po
-rm -f ./$(DEPDIR)/pcem-device.Po
-rm -f ./$(DEPDIR)/pcem-disc.Po
@@ -5288,8 +6854,10 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/pcem-disc_sector.Po
-rm -f ./$(DEPDIR)/pcem-dma.Po
-rm -f ./$(DEPDIR)/pcem-esdi_at.Po
+ -rm -f ./$(DEPDIR)/pcem-f82c710_upc.Po
-rm -f ./$(DEPDIR)/pcem-fdc.Po
-rm -f ./$(DEPDIR)/pcem-fdc37c665.Po
+ -rm -f ./$(DEPDIR)/pcem-fdc37c93x.Po
-rm -f ./$(DEPDIR)/pcem-fdd.Po
-rm -f ./$(DEPDIR)/pcem-fdi2raw.Po
-rm -f ./$(DEPDIR)/pcem-gameport.Po
@@ -5298,10 +6866,14 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/pcem-hdd_file.Po
-rm -f ./$(DEPDIR)/pcem-headland.Po
-rm -f ./$(DEPDIR)/pcem-i430fx.Po
+ -rm -f ./$(DEPDIR)/pcem-i430hx.Po
-rm -f ./$(DEPDIR)/pcem-i430lx.Po
-rm -f ./$(DEPDIR)/pcem-i430vx.Po
+ -rm -f ./$(DEPDIR)/pcem-i440bx.Po
+ -rm -f ./$(DEPDIR)/pcem-i440fx.Po
-rm -f ./$(DEPDIR)/pcem-ide.Po
-rm -f ./$(DEPDIR)/pcem-ide_atapi.Po
+ -rm -f ./$(DEPDIR)/pcem-ide_sff8038i.Po
-rm -f ./$(DEPDIR)/pcem-intel.Po
-rm -f ./$(DEPDIR)/pcem-intel_flash.Po
-rm -f ./$(DEPDIR)/pcem-io.Po
@@ -5332,6 +6904,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/pcem-mouse_msystems.Po
-rm -f ./$(DEPDIR)/pcem-mouse_ps2.Po
-rm -f ./$(DEPDIR)/pcem-mouse_serial.Po
+ -rm -f ./$(DEPDIR)/pcem-mvp3.Po
-rm -f ./$(DEPDIR)/pcem-ne2000.Po
-rm -f ./$(DEPDIR)/pcem-neat.Po
-rm -f ./$(DEPDIR)/pcem-nethandler.Po
@@ -5343,24 +6916,29 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/pcem-paths.Po
-rm -f ./$(DEPDIR)/pcem-pc.Po
-rm -f ./$(DEPDIR)/pcem-pc87306.Po
+ -rm -f ./$(DEPDIR)/pcem-pc87307.Po
-rm -f ./$(DEPDIR)/pcem-pci.Po
-rm -f ./$(DEPDIR)/pcem-pic.Po
-rm -f ./$(DEPDIR)/pcem-piix.Po
+ -rm -f ./$(DEPDIR)/pcem-piix_pm.Po
-rm -f ./$(DEPDIR)/pcem-pit.Po
-rm -f ./$(DEPDIR)/pcem-ppi.Po
-rm -f ./$(DEPDIR)/pcem-ps1.Po
-rm -f ./$(DEPDIR)/pcem-ps2.Po
-rm -f ./$(DEPDIR)/pcem-ps2_mca.Po
-rm -f ./$(DEPDIR)/pcem-ps2_nvr.Po
+ -rm -f ./$(DEPDIR)/pcem-pzx.Po
-rm -f ./$(DEPDIR)/pcem-rom.Po
-rm -f ./$(DEPDIR)/pcem-rtc.Po
-rm -f ./$(DEPDIR)/pcem-rtc_tc8521.Po
+ -rm -f ./$(DEPDIR)/pcem-scamp.Po
-rm -f ./$(DEPDIR)/pcem-scat.Po
-rm -f ./$(DEPDIR)/pcem-scsi.Po
-rm -f ./$(DEPDIR)/pcem-scsi_53c400.Po
-rm -f ./$(DEPDIR)/pcem-scsi_aha1540.Po
-rm -f ./$(DEPDIR)/pcem-scsi_cd.Po
-rm -f ./$(DEPDIR)/pcem-scsi_hd.Po
+ -rm -f ./$(DEPDIR)/pcem-scsi_ibm.Po
-rm -f ./$(DEPDIR)/pcem-scsi_zip.Po
-rm -f ./$(DEPDIR)/pcem-serial.Po
-rm -f ./$(DEPDIR)/pcem-sio.Po
@@ -5371,6 +6949,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/pcem-sound_adlib.Po
-rm -f ./$(DEPDIR)/pcem-sound_adlibgold.Po
-rm -f ./$(DEPDIR)/pcem-sound_audiopci.Po
+ -rm -f ./$(DEPDIR)/pcem-sound_azt2316a.Po
-rm -f ./$(DEPDIR)/pcem-sound_cms.Po
-rm -f ./$(DEPDIR)/pcem-sound_dbopl.Po
-rm -f ./$(DEPDIR)/pcem-sound_emu8k.Po
@@ -5389,6 +6968,8 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/pcem-sound_wss.Po
-rm -f ./$(DEPDIR)/pcem-sound_ym7128.Po
-rm -f ./$(DEPDIR)/pcem-soundopenal.Po
+ -rm -f ./$(DEPDIR)/pcem-sst39sf010.Po
+ -rm -f ./$(DEPDIR)/pcem-superxt.Po
-rm -f ./$(DEPDIR)/pcem-t1000.Po
-rm -f ./$(DEPDIR)/pcem-t3100e.Po
-rm -f ./$(DEPDIR)/pcem-tandy_eeprom.Po
@@ -5405,15 +6986,19 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/pcem-vid_cl5429.Po
-rm -f ./$(DEPDIR)/pcem-vid_colorplus.Po
-rm -f ./$(DEPDIR)/pcem-vid_compaq_cga.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_ddc.Po
-rm -f ./$(DEPDIR)/pcem-vid_ega.Po
-rm -f ./$(DEPDIR)/pcem-vid_et4000.Po
-rm -f ./$(DEPDIR)/pcem-vid_et4000w32.Po
-rm -f ./$(DEPDIR)/pcem-vid_genius.Po
-rm -f ./$(DEPDIR)/pcem-vid_hercules.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_ht216.Po
-rm -f ./$(DEPDIR)/pcem-vid_icd2061.Po
-rm -f ./$(DEPDIR)/pcem-vid_ics2595.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_im1024.Po
-rm -f ./$(DEPDIR)/pcem-vid_incolor.Po
-rm -f ./$(DEPDIR)/pcem-vid_mda.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_mga.Po
-rm -f ./$(DEPDIR)/pcem-vid_olivetti_m24.Po
-rm -f ./$(DEPDIR)/pcem-vid_oti037.Po
-rm -f ./$(DEPDIR)/pcem-vid_oti067.Po
@@ -5422,10 +7007,12 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/pcem-vid_pc1640.Po
-rm -f ./$(DEPDIR)/pcem-vid_pc200.Po
-rm -f ./$(DEPDIR)/pcem-vid_pcjr.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_pgc.Po
-rm -f ./$(DEPDIR)/pcem-vid_ps1_svga.Po
-rm -f ./$(DEPDIR)/pcem-vid_s3.Po
-rm -f ./$(DEPDIR)/pcem-vid_s3_virge.Po
-rm -f ./$(DEPDIR)/pcem-vid_sdac_ramdac.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_sigma.Po
-rm -f ./$(DEPDIR)/pcem-vid_stg_ramdac.Po
-rm -f ./$(DEPDIR)/pcem-vid_svga.Po
-rm -f ./$(DEPDIR)/pcem-vid_svga_render.Po
@@ -5439,8 +7026,22 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/pcem-vid_unk_ramdac.Po
-rm -f ./$(DEPDIR)/pcem-vid_vga.Po
-rm -f ./$(DEPDIR)/pcem-vid_voodoo.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_banshee.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_banshee_blitter.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_blitter.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_display.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_fb.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_fifo.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_reg.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_render.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_setup.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_texture.Po
-rm -f ./$(DEPDIR)/pcem-vid_wy700.Po
-rm -f ./$(DEPDIR)/pcem-video.Po
+ -rm -f ./$(DEPDIR)/pcem-vl82c480.Po
+ -rm -f ./$(DEPDIR)/pcem-vt82c586b.Po
+ -rm -f ./$(DEPDIR)/pcem-w83877tf.Po
+ -rm -f ./$(DEPDIR)/pcem-w83977tf.Po
-rm -f ./$(DEPDIR)/pcem-wd76c10.Po
-rm -f ./$(DEPDIR)/pcem-wx-app.Po
-rm -f ./$(DEPDIR)/pcem-wx-common.Po
@@ -5472,12 +7073,21 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/pcem-wx-utils.Po
-rm -f ./$(DEPDIR)/pcem-x86seg.Po
-rm -f ./$(DEPDIR)/pcem-x87.Po
+ -rm -f ./$(DEPDIR)/pcem-x87_timings.Po
-rm -f ./$(DEPDIR)/pcem-xi8088.Po
-rm -f ./$(DEPDIR)/pcem-xtide.Po
-rm -f dosbox/$(DEPDIR)/pcem-cdrom_image.Po
-rm -f dosbox/$(DEPDIR)/pcem-dbopl.Po
-rm -f dosbox/$(DEPDIR)/pcem-nukedopl.Po
-rm -f dosbox/$(DEPDIR)/pcem-vid_cga_comp.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-cwalk.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-libxml2_encoding.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-minivhd_convert.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-minivhd_create.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-minivhd_io.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-minivhd_manage.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-minivhd_struct_rw.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-minivhd_util.Po
-rm -f resid-fp/$(DEPDIR)/pcem-convolve-sse.Po
-rm -f resid-fp/$(DEPDIR)/pcem-convolve.Po
-rm -f resid-fp/$(DEPDIR)/pcem-envelope.Po
@@ -5560,13 +7170,18 @@ installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/pcem-386.Po
+ -rm -f ./$(DEPDIR)/pcem-386_common.Po
-rm -f ./$(DEPDIR)/pcem-386_dynarec.Po
-rm -f ./$(DEPDIR)/pcem-386_dynarec_ops.Po
-rm -f ./$(DEPDIR)/pcem-808x.Po
+ -rm -f ./$(DEPDIR)/pcem-82091aa.Po
-rm -f ./$(DEPDIR)/pcem-acc2036.Po
+ -rm -f ./$(DEPDIR)/pcem-acc2168.Po
+ -rm -f ./$(DEPDIR)/pcem-acc3221.Po
-rm -f ./$(DEPDIR)/pcem-acer386sx.Po
-rm -f ./$(DEPDIR)/pcem-ali1429.Po
-rm -f ./$(DEPDIR)/pcem-amstrad.Po
+ -rm -f ./$(DEPDIR)/pcem-cassette.Po
-rm -f ./$(DEPDIR)/pcem-cbm_io.Po
-rm -f ./$(DEPDIR)/pcem-cdrom-image.Po
-rm -f ./$(DEPDIR)/pcem-cdrom-ioctl-dummy.Po
@@ -5576,24 +7191,62 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/pcem-cdrom-null.Po
-rm -f ./$(DEPDIR)/pcem-cmd640.Po
-rm -f ./$(DEPDIR)/pcem-codegen.Po
- -rm -f ./$(DEPDIR)/pcem-codegen_backend.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_accumulate.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_allocator.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_arm.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_arm64.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_arm64_imm.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_arm64_ops.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_arm64_uops.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_arm_ops.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_arm_uops.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_x86-64.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86-64_ops.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86-64_ops_sse.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_x86-64_uops.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_x86.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86_ops.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86_ops_fpu.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_backend_x86_ops_sse.Po
-rm -f ./$(DEPDIR)/pcem-codegen_backend_x86_uops.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_block.Po
-rm -f ./$(DEPDIR)/pcem-codegen_ir.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_3dnow.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_arith.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_branch.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_fpu_arith.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_fpu_constant.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_fpu_loadstore.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_fpu_misc.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_helpers.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_jump.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_logic.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_misc.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_mmx_arith.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_mmx_cmp.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_mmx_loadstore.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_mmx_logic.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_mmx_pack.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_mmx_shift.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_mov.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_shift.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_ops_stack.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_reg.Po
-rm -f ./$(DEPDIR)/pcem-codegen_timing_486.Po
-rm -f ./$(DEPDIR)/pcem-codegen_timing_686.Po
-rm -f ./$(DEPDIR)/pcem-codegen_timing_common.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_timing_cyrixiii.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_timing_k6.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_timing_p6.Po
-rm -f ./$(DEPDIR)/pcem-codegen_timing_pentium.Po
-rm -f ./$(DEPDIR)/pcem-codegen_timing_winchip.Po
+ -rm -f ./$(DEPDIR)/pcem-codegen_timing_winchip2.Po
-rm -f ./$(DEPDIR)/pcem-compaq.Po
-rm -f ./$(DEPDIR)/pcem-config.Po
-rm -f ./$(DEPDIR)/pcem-cpu.Po
+ -rm -f ./$(DEPDIR)/pcem-cpu_tables.Po
+ -rm -f ./$(DEPDIR)/pcem-cs8230.Po
-rm -f ./$(DEPDIR)/pcem-dells200.Po
-rm -f ./$(DEPDIR)/pcem-device.Po
-rm -f ./$(DEPDIR)/pcem-disc.Po
@@ -5602,8 +7255,10 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/pcem-disc_sector.Po
-rm -f ./$(DEPDIR)/pcem-dma.Po
-rm -f ./$(DEPDIR)/pcem-esdi_at.Po
+ -rm -f ./$(DEPDIR)/pcem-f82c710_upc.Po
-rm -f ./$(DEPDIR)/pcem-fdc.Po
-rm -f ./$(DEPDIR)/pcem-fdc37c665.Po
+ -rm -f ./$(DEPDIR)/pcem-fdc37c93x.Po
-rm -f ./$(DEPDIR)/pcem-fdd.Po
-rm -f ./$(DEPDIR)/pcem-fdi2raw.Po
-rm -f ./$(DEPDIR)/pcem-gameport.Po
@@ -5612,10 +7267,14 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/pcem-hdd_file.Po
-rm -f ./$(DEPDIR)/pcem-headland.Po
-rm -f ./$(DEPDIR)/pcem-i430fx.Po
+ -rm -f ./$(DEPDIR)/pcem-i430hx.Po
-rm -f ./$(DEPDIR)/pcem-i430lx.Po
-rm -f ./$(DEPDIR)/pcem-i430vx.Po
+ -rm -f ./$(DEPDIR)/pcem-i440bx.Po
+ -rm -f ./$(DEPDIR)/pcem-i440fx.Po
-rm -f ./$(DEPDIR)/pcem-ide.Po
-rm -f ./$(DEPDIR)/pcem-ide_atapi.Po
+ -rm -f ./$(DEPDIR)/pcem-ide_sff8038i.Po
-rm -f ./$(DEPDIR)/pcem-intel.Po
-rm -f ./$(DEPDIR)/pcem-intel_flash.Po
-rm -f ./$(DEPDIR)/pcem-io.Po
@@ -5646,6 +7305,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/pcem-mouse_msystems.Po
-rm -f ./$(DEPDIR)/pcem-mouse_ps2.Po
-rm -f ./$(DEPDIR)/pcem-mouse_serial.Po
+ -rm -f ./$(DEPDIR)/pcem-mvp3.Po
-rm -f ./$(DEPDIR)/pcem-ne2000.Po
-rm -f ./$(DEPDIR)/pcem-neat.Po
-rm -f ./$(DEPDIR)/pcem-nethandler.Po
@@ -5657,24 +7317,29 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/pcem-paths.Po
-rm -f ./$(DEPDIR)/pcem-pc.Po
-rm -f ./$(DEPDIR)/pcem-pc87306.Po
+ -rm -f ./$(DEPDIR)/pcem-pc87307.Po
-rm -f ./$(DEPDIR)/pcem-pci.Po
-rm -f ./$(DEPDIR)/pcem-pic.Po
-rm -f ./$(DEPDIR)/pcem-piix.Po
+ -rm -f ./$(DEPDIR)/pcem-piix_pm.Po
-rm -f ./$(DEPDIR)/pcem-pit.Po
-rm -f ./$(DEPDIR)/pcem-ppi.Po
-rm -f ./$(DEPDIR)/pcem-ps1.Po
-rm -f ./$(DEPDIR)/pcem-ps2.Po
-rm -f ./$(DEPDIR)/pcem-ps2_mca.Po
-rm -f ./$(DEPDIR)/pcem-ps2_nvr.Po
+ -rm -f ./$(DEPDIR)/pcem-pzx.Po
-rm -f ./$(DEPDIR)/pcem-rom.Po
-rm -f ./$(DEPDIR)/pcem-rtc.Po
-rm -f ./$(DEPDIR)/pcem-rtc_tc8521.Po
+ -rm -f ./$(DEPDIR)/pcem-scamp.Po
-rm -f ./$(DEPDIR)/pcem-scat.Po
-rm -f ./$(DEPDIR)/pcem-scsi.Po
-rm -f ./$(DEPDIR)/pcem-scsi_53c400.Po
-rm -f ./$(DEPDIR)/pcem-scsi_aha1540.Po
-rm -f ./$(DEPDIR)/pcem-scsi_cd.Po
-rm -f ./$(DEPDIR)/pcem-scsi_hd.Po
+ -rm -f ./$(DEPDIR)/pcem-scsi_ibm.Po
-rm -f ./$(DEPDIR)/pcem-scsi_zip.Po
-rm -f ./$(DEPDIR)/pcem-serial.Po
-rm -f ./$(DEPDIR)/pcem-sio.Po
@@ -5685,6 +7350,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/pcem-sound_adlib.Po
-rm -f ./$(DEPDIR)/pcem-sound_adlibgold.Po
-rm -f ./$(DEPDIR)/pcem-sound_audiopci.Po
+ -rm -f ./$(DEPDIR)/pcem-sound_azt2316a.Po
-rm -f ./$(DEPDIR)/pcem-sound_cms.Po
-rm -f ./$(DEPDIR)/pcem-sound_dbopl.Po
-rm -f ./$(DEPDIR)/pcem-sound_emu8k.Po
@@ -5703,6 +7369,8 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/pcem-sound_wss.Po
-rm -f ./$(DEPDIR)/pcem-sound_ym7128.Po
-rm -f ./$(DEPDIR)/pcem-soundopenal.Po
+ -rm -f ./$(DEPDIR)/pcem-sst39sf010.Po
+ -rm -f ./$(DEPDIR)/pcem-superxt.Po
-rm -f ./$(DEPDIR)/pcem-t1000.Po
-rm -f ./$(DEPDIR)/pcem-t3100e.Po
-rm -f ./$(DEPDIR)/pcem-tandy_eeprom.Po
@@ -5719,15 +7387,19 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/pcem-vid_cl5429.Po
-rm -f ./$(DEPDIR)/pcem-vid_colorplus.Po
-rm -f ./$(DEPDIR)/pcem-vid_compaq_cga.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_ddc.Po
-rm -f ./$(DEPDIR)/pcem-vid_ega.Po
-rm -f ./$(DEPDIR)/pcem-vid_et4000.Po
-rm -f ./$(DEPDIR)/pcem-vid_et4000w32.Po
-rm -f ./$(DEPDIR)/pcem-vid_genius.Po
-rm -f ./$(DEPDIR)/pcem-vid_hercules.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_ht216.Po
-rm -f ./$(DEPDIR)/pcem-vid_icd2061.Po
-rm -f ./$(DEPDIR)/pcem-vid_ics2595.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_im1024.Po
-rm -f ./$(DEPDIR)/pcem-vid_incolor.Po
-rm -f ./$(DEPDIR)/pcem-vid_mda.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_mga.Po
-rm -f ./$(DEPDIR)/pcem-vid_olivetti_m24.Po
-rm -f ./$(DEPDIR)/pcem-vid_oti037.Po
-rm -f ./$(DEPDIR)/pcem-vid_oti067.Po
@@ -5736,10 +7408,12 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/pcem-vid_pc1640.Po
-rm -f ./$(DEPDIR)/pcem-vid_pc200.Po
-rm -f ./$(DEPDIR)/pcem-vid_pcjr.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_pgc.Po
-rm -f ./$(DEPDIR)/pcem-vid_ps1_svga.Po
-rm -f ./$(DEPDIR)/pcem-vid_s3.Po
-rm -f ./$(DEPDIR)/pcem-vid_s3_virge.Po
-rm -f ./$(DEPDIR)/pcem-vid_sdac_ramdac.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_sigma.Po
-rm -f ./$(DEPDIR)/pcem-vid_stg_ramdac.Po
-rm -f ./$(DEPDIR)/pcem-vid_svga.Po
-rm -f ./$(DEPDIR)/pcem-vid_svga_render.Po
@@ -5753,8 +7427,22 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/pcem-vid_unk_ramdac.Po
-rm -f ./$(DEPDIR)/pcem-vid_vga.Po
-rm -f ./$(DEPDIR)/pcem-vid_voodoo.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_banshee.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_banshee_blitter.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_blitter.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_display.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_fb.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_fifo.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_reg.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_render.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_setup.Po
+ -rm -f ./$(DEPDIR)/pcem-vid_voodoo_texture.Po
-rm -f ./$(DEPDIR)/pcem-vid_wy700.Po
-rm -f ./$(DEPDIR)/pcem-video.Po
+ -rm -f ./$(DEPDIR)/pcem-vl82c480.Po
+ -rm -f ./$(DEPDIR)/pcem-vt82c586b.Po
+ -rm -f ./$(DEPDIR)/pcem-w83877tf.Po
+ -rm -f ./$(DEPDIR)/pcem-w83977tf.Po
-rm -f ./$(DEPDIR)/pcem-wd76c10.Po
-rm -f ./$(DEPDIR)/pcem-wx-app.Po
-rm -f ./$(DEPDIR)/pcem-wx-common.Po
@@ -5786,12 +7474,21 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/pcem-wx-utils.Po
-rm -f ./$(DEPDIR)/pcem-x86seg.Po
-rm -f ./$(DEPDIR)/pcem-x87.Po
+ -rm -f ./$(DEPDIR)/pcem-x87_timings.Po
-rm -f ./$(DEPDIR)/pcem-xi8088.Po
-rm -f ./$(DEPDIR)/pcem-xtide.Po
-rm -f dosbox/$(DEPDIR)/pcem-cdrom_image.Po
-rm -f dosbox/$(DEPDIR)/pcem-dbopl.Po
-rm -f dosbox/$(DEPDIR)/pcem-nukedopl.Po
-rm -f dosbox/$(DEPDIR)/pcem-vid_cga_comp.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-cwalk.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-libxml2_encoding.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-minivhd_convert.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-minivhd_create.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-minivhd_io.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-minivhd_manage.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-minivhd_struct_rw.Po
+ -rm -f minivhd/$(DEPDIR)/pcem-minivhd_util.Po
-rm -f resid-fp/$(DEPDIR)/pcem-convolve-sse.Po
-rm -f resid-fp/$(DEPDIR)/pcem-convolve.Po
-rm -f resid-fp/$(DEPDIR)/pcem-envelope.Po
@@ -5873,6 +7570,14 @@ wx.res: wx.rc
wx-resources.cpp : pc.xrc
-wxrc -c pc.xrc -o wx-resources.cpp
+#pcem_CFLAGS += -mtune=cortex-a53
+#pcem_CXXFLAGS += -mtune=cortex-a53
+#pcem_LDFLAGS = -flto -O3 -mtune=cortex-a15
+
+# pcem_CFLAGS += -fprofile-use
+# pcem_CXXFLAGS += -fprofile-use
+# pcem_LDFLAGS = -fprofile-use
+
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/src/Makefile.linux32-wx-sdl2 b/src/Makefile.linux32-wx-sdl2
deleted file mode 100644
index 861ec27..0000000
--- a/src/Makefile.linux32-wx-sdl2
+++ /dev/null
@@ -1,52 +0,0 @@
-VPATH = . dosbox resid-fp
-CPP = g++
-CC = gcc
-WXRC = wxrc
-CFLAGS = -O3 -fomit-frame-pointer -msse2 -m32 $(shell wx-config --cxxflags) $(shell sdl2-config --cflags)
-CXXFLAGS = $(CFLAGS)
-OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl-linux.o cdrom-image.o cdrom-null.o \
-cmd640.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_common.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.c compaq.o config.o cpu.o \
-dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \
-hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o i430vx.o ide.o ide_atapi.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \
-joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o \
-laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o mouse_serial.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o \
-opti495.o paths.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o rom.o rtc.o rtc_tc8521.o scat.o scsi.o scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_zip.o \
-serial.o sio.o sis496.o sl82c460.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_emu8k.o sound_gus.o \
-sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_sb.o sound_sb_dsp.o sound_sn76489.o \
-sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o \
-timer.o um8669f.o um8881f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o \
-vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o vid_genius.o vid_hercules.o \
-vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc200.o \
-vid_pc1512.o vid_pc1640.o vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o \
-vid_stg_ramdac.o vid_svga.o vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o \
-vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_wy700.o video.o wd76c10.o \
-x86seg.o x87.o xi8088.c xtide.o sound_dbopl.o sound_resid.o \
-wx-main.o wx-config_sel.o wx-dialogbox.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o wx-sdl2-keyboard.o wx-sdl2-video.o wx-sdl2-midi.o \
-wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o wx-sdl2-status.o wx-resources.o wx-thread.o wx-common.o wx-sdl2-display.o \
-wx-sdl2-video-renderer.o wx-sdl2-video-gl3.o wx-glslp-parser.o wx-shader_man.o wx-shaderconfig.o wx-joystickconfig.o wx-createdisc.o
-DBOBJ = cdrom_image.o dbopl.o nukedopl.o vid_cga_comp.o
-SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
-
-LIBS = -lopenal -lstdc++ -lpthread -lm $(shell wx-config --libs) $(shell sdl2-config --libs) -lGL
-
-PCem-wx-SDL2: $(OBJ) $(DBOBJ) $(SIDOBJ)
- $(CC) $(OBJ) $(DBOBJ) $(SIDOBJ) -o "PCem-wx-SDL2" $(LIBS)
-
-all : PCem-wx-SDL2
-
-clean :
- rm *.o
- rm PCem-wx-SDL2
-
-wx-resources.o : pc.xrc
- $(WXRC) -c pc.xrc -o wx-resources.cpp
- $(CPP) $(CFLAGS) -c wx-resources.cpp
-
-%.o : %.c
- $(CC) $(CFLAGS) -c $<
-
-%.o : %.cc
- $(CPP) $(CXXFLAGS) -c $<
-
-%.o : %.cpp
- $(CPP) $(CXXFLAGS) -c $<
diff --git a/src/Makefile.linux64-wx-sdl2 b/src/Makefile.linux64-wx-sdl2
deleted file mode 100644
index 4b2e9e3..0000000
--- a/src/Makefile.linux64-wx-sdl2
+++ /dev/null
@@ -1,52 +0,0 @@
-VPATH = . dosbox resid-fp
-CPP = g++
-CC = gcc
-WXRC = wxrc
-CFLAGS = -O3 -fomit-frame-pointer -msse2 -m64 $(shell wx-config --cxxflags) $(shell sdl2-config --cflags)
-CXXFLAGS = $(CFLAGS)
-OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl-linux.o cdrom-image.o cdrom-null.o \
-cmd640.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_common.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.c compaq.o config.o cpu.o \
-dells200.o device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \
-hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o i430vx.o ide.o ide_atapi.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \
-joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o \
-laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o mouse_serial.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o \
-opti495.o paths.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o rom.o rtc.o rtc_tc8521.o scat.o scsi.o scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_zip.o \
-serial.o sio.o sis496.o sl82c460.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_emu8k.o sound_gus.o \
-sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_sb.o sound_sb_dsp.o sound_sn76489.o \
-sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o \
-timer.o um8669f.o um8881f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o \
-vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o vid_genius.o vid_hercules.o \
-vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc200.o \
-vid_pc1512.o vid_pc1640.o vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o \
-vid_stg_ramdac.o vid_svga.o vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o \
-vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_wy700.o video.o wd76c10.o \
-x86seg.o x87.o xi8088.c xtide.o sound_dbopl.o sound_resid.o \
-wx-main.o wx-config_sel.o wx-dialogbox.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o wx-sdl2-keyboard.o wx-sdl2-video.o wx-sdl2-midi.o \
-wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o wx-sdl2-status.o wx-resources.o wx-thread.o wx-common.o wx-sdl2-display.o \
-wx-sdl2-video-renderer.o wx-sdl2-video-gl3.o wx-glslp-parser.o wx-shader_man.o wx-shaderconfig.o wx-joystickconfig.o wx-createdisc.o
-DBOBJ = cdrom_image.o dbopl.o nukedopl.o vid_cga_comp.o
-SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
-
-LIBS = -lopenal -lstdc++ -lpthread -lm $(shell wx-config --libs) $(shell sdl2-config --libs) -lGL
-
-PCem64-wx-SDL2: $(OBJ) $(DBOBJ) $(SIDOBJ)
- $(CC) $(OBJ) $(DBOBJ) $(SIDOBJ) -o "PCem64-wx-SDL2" $(LIBS)
-
-all : PCem64-wx-SDL2
-
-clean :
- rm *.o
- rm PCem64-wx-SDL2
-
-wx-resources.o : pc.xrc
- $(WXRC) -c pc.xrc -o wx-resources.cpp
- $(CPP) $(CFLAGS) -c wx-resources.cpp
-
-%.o : %.c
- $(CC) $(CFLAGS) -c $<
-
-%.o : %.cc
- $(CPP) $(CXXFLAGS) -c $<
-
-%.o : %.cpp
- $(CPP) $(CXXFLAGS) -c $<
diff --git a/src/Makefile.mingw-wx-sdl2 b/src/Makefile.mingw-wx-sdl2
index 8414549..cc37a09 100644
--- a/src/Makefile.mingw-wx-sdl2
+++ b/src/Makefile.mingw-wx-sdl2
@@ -1,4 +1,4 @@
-VPATH = . dosbox resid-fp
+VPATH = . dosbox resid-fp minivhd
CPP = g++
CC = gcc
WINDRES = windres.exe
@@ -6,38 +6,40 @@ WXVERSION = 31
WXINCLUDE = e:/MinGWget/include/wx/
CFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign -Werror -fno-strict-aliasing
CXXFLAGS = $(CFLAGS)
-OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o \
+OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc2036.o acc2168.o acc3221.o acer386sx.o ali1429.o amstrad.o cassette.o \
cbm_io.o cdrom-ioctl.o cdrom-image.o cmd640.o codegen.o codegen_accumulate.o codegen_allocator.o \
- codegen_backend.o codegen_backend_x86.o codegen_backend_x86_ops.o codegen_backend_x86_ops_fpu.o \
- codegen_backend_x86_ops_sse.o codegen_backend_x86_uops.o codegen_ir.o codegen_ops.o \
+ codegen_backend_x86.o codegen_backend_x86_ops.o codegen_backend_x86_ops_fpu.o codegen_backend_x86_ops_sse.o \
+ codegen_backend_x86_uops.o codegen_block.o codegen_ir.o codegen_ops.o \
codegen_ops_3dnow.o codegen_ops_branch.o codegen_ops_arith.o codegen_ops_fpu_arith.o \
codegen_ops_fpu_constant.o codegen_ops_fpu_loadstore.o codegen_ops_fpu_misc.o codegen_ops_helpers.o codegen_ops_jump.o \
codegen_ops_logic.o codegen_ops_misc.o codegen_ops_mmx_arith.o codegen_ops_mmx_cmp.o \
codegen_ops_mmx_loadstore.o codegen_ops_mmx_logic.o codegen_ops_mmx_pack.o codegen_ops_mmx_shift.o \
codegen_ops_mov.o codegen_ops_shift.o codegen_ops_stack.o codegen_reg.o codegen_timing_486.o \
- codegen_timing_686.o codegen_timing_common.o codegen_timing_k6.o codegen_timing_pentium.o \
- codegen_timing_winchip.o codegen_timing_winchip2.o compaq.o config.o cpu.o cpu_tables.o device.o \
- dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o \
- fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o i430vx.o ide.o \
+ codegen_timing_686.o codegen_timing_common.o codegen_timing_cyrixiii.o codegen_timing_k6.o codegen_timing_p6.o codegen_timing_pentium.o \
+ codegen_timing_winchip.o codegen_timing_winchip2.o compaq.o config.o cpu.o cpu_tables.o cs8230.o device.o \
+ dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o f82c710_upc.o fdc.o fdc37c665.o fdc37c93x.o fdd.o \
+ fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430hx.o i430lx.o i430fx.o i430vx.o i440fx.o i440bx.o ide.o \
ide_atapi.o ide_sff8038i.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o \
joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o \
mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o mouse_serial.o \
- mvp3.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pci.o pic.o \
- piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o rom.o rtc.o rtc_tc8521.o scat.o scsi.o \
- scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o \
- sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_dbopl.o \
+ mvp3.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pc87307.o pci.o pic.o \
+ piix.o piix_pm.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o scamp.o scat.o scsi.o \
+ scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_ibm.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o \
+ sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_azt2316a.o sound_cms.o sound_dbopl.o \
sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \
sound_resid.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \
- sound_ym7128.o soundopenal.o sst39sf010.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \
+ sound_ym7128.o soundopenal.o sst39sf010.o superxt.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \
vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o \
- vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o \
- vid_et4000w32i.o vid_genius.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \
- vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \
- vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \
+ vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ddc.o vid_ega.o vid_et4000.o vid_et4000w32.o \
+ vid_et4000w32i.o vid_genius.o vid_hercules.o vid_ht216.o vid_icd2061.o vid_ics2595.o vid_im1024.o vid_incolor.o vid_mda.o \
+ vid_mga.o vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \
+ vid_pcjr.o vid_pgc.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_sigma.o vid_stg_ramdac.o vid_svga.o \
vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o \
- vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_wy700.o video.o \
- vt82c586b.o w83877tf.o wd76c10.o x86seg.o x87.o xi8088.c xtide.o win-midi.o wx-main.o \
+ vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_voodoo_banshee.o vid_voodoo_banshee_blitter.o \
+ vid_voodoo_blitter.o vid_voodoo_display.o vid_voodoo_fb.o vid_voodoo_fifo.o vid_voodoo_reg.o \
+ vid_voodoo_render.o vid_voodoo_setup.o vid_voodoo_texture.o vid_wy700.o video.o vl82c480.o \
+ vt82c586b.o w83877tf.o w83977tf.o wd76c10.o x86seg.o x87.o x87_timings.o xi8088.c xtide.o zenith.o win-midi.o wx-main.o \
wx-config_sel.o wx-dialogbox.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o \
wx-sdl2-keyboard.o wx-sdl2-video.o wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o \
wx-sdl2-status.o wx-resources.o wx-thread.o wx-common.o wx-sdl2-display-win.o \
@@ -45,11 +47,12 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer38
wx-joystickconfig.o wx-createdisc.o wx.res
DBOBJ = cdrom_image.o dbopl.o nukedopl.o vid_cga_comp.o
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
+MVHDOBJ = cwalk.o libxml2_encoding.o minivhd_convert.o minivhd_create.o minivhd_io.o minivhd_manage.o minivhd_struct_rw.o minivhd_util.o
LIBS = -Wl,--subsystem,windows -mthreads -mwindows -lwxmsw$(WXVERSION)u_xrc -lwxmsw$(WXVERSION)u_html -lwxmsw$(WXVERSION)u_adv -lwxbase$(WXVERSION)u_xml -lwxmsw$(WXVERSION)u_core -lwxbase$(WXVERSION)u -lwxtiff -lwxjpeg -lwxpng -lwxzlib -lwxregexu -lwxexpat -lkernel32 -lcomdlg32 -lwinspool -lcomctl32 -lole32 -loleaut32 -luuid -lrpcrt4 -ladvapi32 -lmingw32 -lopengl32 -lopenal32 -lstdc++ -lSDL2main -lSDL2 -lm -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -static-libgcc
-PCem-wx-SDL2.exe: $(OBJ) $(DBOBJ) $(SIDOBJ)
- $(CC) $(OBJ) $(DBOBJ) $(SIDOBJ) -o "PCem-wx-SDL2.exe" $(LIBS)
+PCem-wx-SDL2.exe: $(OBJ) $(DBOBJ) $(SIDOBJ) $(MVHDOBJ)
+ $(CC) $(OBJ) $(DBOBJ) $(SIDOBJ) $(MVHDOBJ) -o "PCem-wx-SDL2.exe" $(LIBS)
strip -s PCem-wx-SDL2.exe
all : PCem-wx-SDL2.exe
diff --git a/src/Makefile.mingw-wx-sdl2-network b/src/Makefile.mingw-wx-sdl2-network
index 20bc8bd..c1d7771 100644
--- a/src/Makefile.mingw-wx-sdl2-network
+++ b/src/Makefile.mingw-wx-sdl2-network
@@ -1,4 +1,4 @@
-VPATH = . dosbox resid-fp
+VPATH = . dosbox resid-fp minivhd
CPP = g++
CC = gcc
WINDRES = windres.exe
@@ -6,33 +6,54 @@ WXVERSION = 31
WXINCLUDE = e:/mingwget/include/wx/
CFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign -Werror -fno-strict-aliasing -DUSE_NETWORKING
CXXFLAGS = $(CFLAGS)
-OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl.o cdrom-image.o \
- cmd640.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_common.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o \
- device.o dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o \
- i430vx.o ide.o ide_atapi.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
- keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o \
- mouse_serial.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o rom.o rtc.o rtc_tc8521.o \
- scat.o scsi.o scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_dbopl.o \
- sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \
- sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \
- sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \
- vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o \
- vid_et4000w32.o vid_et4000w32i.o vid_genius.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \
- vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \
- vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \
- vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \
- vid_vga.o vid_voodoo.o vid_wy700.o video.o wd76c10.o x86seg.o x87.o xi8088.c xtide.o win-midi.o \
- wx-main.o wx-config_sel.o wx-dialogbox.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o wx-sdl2-keyboard.o wx-sdl2-video.o \
- wx-sdl2.o wx-config.o wx-deviceconfig.o wx-hostconfig.o wx-status.o wx-sdl2-status.o wx-resources.o wx-thread.o wx-common.o wx-sdl2-display-win.o \
- wx-sdl2-video-renderer.o wx-sdl2-video-gl3.o wx-glslp-parser.o wx-shader_man.o wx-shaderconfig.o wx-joystickconfig.o wx-createdisc.o wx.res
+OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc2036.o acc2168.o acc3221.o acer386sx.o ali1429.o amstrad.o cassette.o \
+ cbm_io.o cdrom-ioctl.o cdrom-image.o cmd640.o codegen.o codegen_accumulate.o codegen_allocator.o \
+ codegen_backend_x86.o codegen_backend_x86_ops.o codegen_backend_x86_ops_fpu.o codegen_backend_x86_ops_sse.o \
+ codegen_backend_x86_uops.o codegen_block.o codegen_ir.o codegen_ops.o \
+ codegen_ops_3dnow.o codegen_ops_branch.o codegen_ops_arith.o codegen_ops_fpu_arith.o \
+ codegen_ops_fpu_constant.o codegen_ops_fpu_loadstore.o codegen_ops_fpu_misc.o codegen_ops_helpers.o codegen_ops_jump.o \
+ codegen_ops_logic.o codegen_ops_misc.o codegen_ops_mmx_arith.o codegen_ops_mmx_cmp.o \
+ codegen_ops_mmx_loadstore.o codegen_ops_mmx_logic.o codegen_ops_mmx_pack.o codegen_ops_mmx_shift.o \
+ codegen_ops_mov.o codegen_ops_shift.o codegen_ops_stack.o codegen_reg.o codegen_timing_486.o \
+ codegen_timing_686.o codegen_timing_common.o codegen_timing_cyrixiii.o codegen_timing_k6.o codegen_timing_p6.o codegen_timing_pentium.o \
+ codegen_timing_winchip.o codegen_timing_winchip2.o compaq.o config.o cpu.o cpu_tables.o cs8230.o device.o \
+ dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o f82c710_upc.o fdc.o fdc37c665.o fdc37c93x.o fdd.o \
+ fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430hx.o i430lx.o i430fx.o i430vx.o i440fx.o i440bx.o ide.o \
+ ide_atapi.o ide_sff8038i.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o \
+ joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
+ keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o \
+ mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o mouse_serial.o \
+ mvp3.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pc87307.o pci.o pic.o \
+ piix.o piix_pm.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o scamp.o scat.o scsi.o \
+ scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_ibm.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o \
+ sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_azt2316a.o sound_cms.o sound_dbopl.o \
+ sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \
+ sound_resid.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \
+ sound_ym7128.o soundopenal.o sst39sf010.o superxt.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \
+ vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o \
+ vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ddc.o vid_ega.o vid_et4000.o vid_et4000w32.o \
+ vid_et4000w32i.o vid_genius.o vid_hercules.o vid_ht216.o vid_icd2061.o vid_ics2595.o vid_im1024.o vid_incolor.o vid_mda.o \
+ vid_mga.o vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \
+ vid_pcjr.o vid_pgc.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_sigma.o vid_stg_ramdac.o vid_svga.o \
+ vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o \
+ vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_voodoo_banshee.o vid_voodoo_banshee_blitter.o \
+ vid_voodoo_blitter.o vid_voodoo_display.o vid_voodoo_fb.o vid_voodoo_fifo.o vid_voodoo_reg.o \
+ vid_voodoo_render.o vid_voodoo_setup.o vid_voodoo_texture.o vid_wy700.o video.o vl82c480.o \
+ vt82c586b.o w83877tf.o w83977tf.o wd76c10.o x86seg.o x87.o x87_timings.o xi8088.c xtide.o zenith.o win-midi.o wx-main.o \
+ wx-config_sel.o wx-dialogbox.o wx-hostconfig.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o \
+ wx-sdl2-keyboard.o wx-sdl2-video.o wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o \
+ wx-sdl2-status.o wx-resources.o wx-thread.o wx-common.o wx-sdl2-display-win.o \
+ wx-sdl2-video-renderer.o wx-sdl2-video-gl3.o wx-glslp-parser.o wx-shader_man.o wx-shaderconfig.o \
+ wx-joystickconfig.o wx-createdisc.o wx.res
DBOBJ = cdrom_image.o dbopl.o nukedopl.o vid_cga_comp.o
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
+MVHDOBJ = cwalk.o libxml2_encoding.o minivhd_convert.o minivhd_create.o minivhd_io.o minivhd_manage.o minivhd_struct_rw.o minivhd_util.o
NETOBJ = ne2000.o nethandler.o
LIBS = -Wl,--subsystem,windows -mthreads -mwindows -lwxmsw$(WXVERSION)u_xrc -lwxmsw$(WXVERSION)u_html -lwxmsw$(WXVERSION)u_adv -lwxbase$(WXVERSION)u_xml -lwxmsw$(WXVERSION)u_core -lwxbase$(WXVERSION)u -lwxtiff -lwxjpeg -lwxpng -lwxzlib -lwxregexu -lwxexpat -lkernel32 -lcomdlg32 -lwinspool -lcomctl32 -lole32 -loleaut32 -luuid -lrpcrt4 -ladvapi32 -lmingw32 -lopengl32 -lopenal32 -lstdc++ -lSDL2main -lSDL2 -lm -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -static-libgcc -lwsock32 -liphlpapi
-PCem-wx-SDL2.exe: $(OBJ) $(DBOBJ) $(SIDOBJ) $(NETOBJ) libslirp.a
- $(CC) $(OBJ) $(DBOBJ) $(SIDOBJ) $(NETOBJ) slirp/libslirp.a -o "PCem-wx-SDL2.exe" $(LIBS)
+PCem-wx-SDL2.exe: $(OBJ) $(DBOBJ) $(SIDOBJ) $(MVHDOBJ) $(NETOBJ) libslirp.a
+ $(CC) $(OBJ) $(DBOBJ) $(SIDOBJ) $(MVHDOBJ) $(NETOBJ) slirp/libslirp.a -o "PCem-wx-SDL2.exe" $(LIBS)
strip -s PCem-wx-SDL2.exe
libslirp.a:
diff --git a/src/Makefile.osx64-wx-sdl2 b/src/Makefile.osx64-wx-sdl2
deleted file mode 100644
index 2549db1..0000000
--- a/src/Makefile.osx64-wx-sdl2
+++ /dev/null
@@ -1,51 +0,0 @@
-VPATH = . dosbox resid-fp
-CPP = g++
-CC = gcc
-WXRC = wxrc
-CFLAGS = -D__unix=1 -DPCEM_RENDER_WITH_TIMER -DPCEM_RENDER_TIMER_LOOP -Dfopen64=fopen -Dfseeko64=fseeko -Dftello64=ftello -Doff64_t=off_t -O3 -fomit-frame-pointer -msse2 -m64 $(shell wx-config --cxxflags) $(shell sdl2-config --cflags) -I/usr/local/opt/openal-soft/include -I/usr/local/include
-OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o cbm_io.o cdrom-ioctl-osx.o cdrom-image.o cdrom-null.o \
-cmd640.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_common.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.c compaq.o config.o cpu.o \
-device.o dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o \
-hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o i430vx.o ide.o ide_atapi.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o \
-joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o \
-laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o mouse_serial.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o \
-opti495.o paths.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o rom.o rtc.o rtc_tc8521.o scat.o scsi.o scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_zip.o \
-serial.o sio.o sis496.o sl82c460.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_emu8k.o sound_gus.o \
-sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_sb.o sound_sb_dsp.o sound_sn76489.o \
-sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o \
-timer.o um8669f.o um8881f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o \
-vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o vid_genius.o vid_hercules.o \
-vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc200.o \
-vid_pc1512.o vid_pc1640.o vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o \
-vid_stg_ramdac.o vid_svga.o vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o \
-vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_wy700.o video.o wd76c10.o \
-x86seg.o x87.o xi8088.c xtide.o sound_dbopl.o sound_resid.o \
-wx-main.o wx-config_sel.o wx-dialogbox.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o wx-sdl2-keyboard.o wx-sdl2-video.o wx-sdl2-midi.o \
-wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o wx-sdl2-status.o wx-resources.o wx-thread.o wx-common.o wx-sdl2-display.o \
-wx-sdl2-video-renderer.o wx-sdl2-video-gl3.o wx-glslp-parser.o wx-shader_man.o wx-shaderconfig.o wx-joystickconfig.o wx-createdisc.o
-DBOBJ = cdrom_image.o dbopl.o nukedopl.o vid_cga_comp.o
-SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o
-
-LIBS = -lopenal -lstdc++ -lpthread -lm $(shell wx-config --libs) $(shell sdl2-config --libs) -L/usr/local/opt/openal-soft/lib -framework OpenGL
-
-PCem64-wx-SDL2: $(OBJ) $(DBOBJ) $(SIDOBJ)
- $(CC) $(OBJ) $(DBOBJ) $(SIDOBJ) -o "PCem64-wx-SDL2" $(LIBS)
-
-all : PCem64-wx-SDL2
-
-clean :
- rm *.o
- rm PCem64-wx-SDL2
-
-wx-resources.o : pc.xrc
- $(WXRC) -c pc.xrc -o wx-resources.cpp
- $(CPP) $(CFLAGS) -c wx-resources.cpp
-
-%.o : %.c
- $(CC) $(CFLAGS) -c $<
-
-%.o : %.cc
- $(CPP) $(CFLAGS) -c $<
-
-%.o : %.cpp
- $(CPP) $(CFLAGS) -c $<
diff --git a/src/acc2036.c b/src/acc2036.c
index bf511fb..faacd9d 100644
--- a/src/acc2036.c
+++ b/src/acc2036.c
@@ -88,6 +88,9 @@ static uint8_t acc2036_read(uint16_t addr, void *p)
{
if (!(addr & 1))
return acc2036.reg_idx;
+
+ if (acc2036.reg_idx >= 0xbc)
+ return 0xff;
return acc2036.regs[acc2036.reg_idx];
}
diff --git a/src/acc2168.c b/src/acc2168.c
new file mode 100644
index 0000000..e6ab7dd
--- /dev/null
+++ b/src/acc2168.c
@@ -0,0 +1,119 @@
+#include "ibm.h"
+#include "acc2168.h"
+#include "cpu.h"
+#include "io.h"
+#include "mem.h"
+#include "x86.h"
+
+static struct
+{
+ int reg_idx;
+ uint8_t regs[256];
+ uint8_t port_62;
+} acc2168;
+
+static void acc2168_shadow_recalc()
+{
+ if (acc2168.regs[0x02] & 8)
+ {
+ switch (acc2168.regs[0x02] & 0x30)
+ {
+ case 0x00:
+ mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ case 0x10:
+ mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ case 0x20:
+ mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 0x30:
+ mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ }
+ }
+ else
+ mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+
+ if (acc2168.regs[0x02] & 4)
+ {
+ switch (acc2168.regs[0x02] & 0x30)
+ {
+ case 0x00:
+ mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ case 0x10:
+ mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ case 0x20:
+ mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 0x30:
+ mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ }
+ }
+ else
+ mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+}
+
+static void acc2168_write(uint16_t addr, uint8_t val, void *p)
+{
+// pclog("acc2168_write: addr=%04x val=%02x\n", addr, val);
+ if (!(addr & 1))
+ acc2168.reg_idx = val;
+ else
+ {
+ acc2168.regs[acc2168.reg_idx] = val;
+// pclog("acc2168_write: idx=%02x val=%02x %04x:%04x\n", acc2168.reg_idx, val, CS,cpu_state.pc);
+
+ switch (acc2168.reg_idx)
+ {
+ case 0x02:
+ acc2168_shadow_recalc();
+ break;
+ }
+ }
+}
+
+static uint8_t acc2168_read(uint16_t addr, void *p)
+{
+ if (!(addr & 1))
+ return acc2168.reg_idx;
+
+// pclog("acc2168_read: idx=%02x val=%02x\n", acc2168.reg_idx, acc2168.regs[acc2168.reg_idx]);
+ return acc2168.regs[acc2168.reg_idx];
+}
+
+static uint8_t port78_read(uint16_t addr, void *p)
+{
+ return 0;
+}
+
+static uint8_t port92_read(uint16_t addr, void *p)
+{
+ return acc2168.port_62 | 0xfc;
+}
+
+static void port92_write(uint16_t addr, uint8_t val, void *p)
+{
+ if ((mem_a20_alt ^ val) & 2)
+ {
+ mem_a20_alt = val & 2;
+ mem_a20_recalc();
+ }
+ if ((~acc2168.port_62 & val) & 1)
+ {
+ softresetx86();
+ cpu_set_edx();
+ }
+ acc2168.port_62 = val | 0xfC;
+}
+
+void acc2168_init()
+{
+ memset(&acc2168, 0, sizeof(acc2168));
+ io_sethandler(0x00f2, 0x0002, acc2168_read, NULL, NULL, acc2168_write, NULL, NULL, NULL);
+ io_sethandler(0x0078, 0x0001, port78_read, NULL, NULL, NULL, NULL, NULL, NULL);
+ io_sethandler(0x0092, 0x0001, port92_read, NULL, NULL, port92_write, NULL, NULL, NULL);
+}
diff --git a/src/acc2168.h b/src/acc2168.h
new file mode 100644
index 0000000..93515ee
--- /dev/null
+++ b/src/acc2168.h
@@ -0,0 +1 @@
+void acc2168_init();
diff --git a/src/acc3221.c b/src/acc3221.c
new file mode 100644
index 0000000..2b3fb8a
--- /dev/null
+++ b/src/acc3221.c
@@ -0,0 +1,122 @@
+#include "ibm.h"
+#include "acc3221.h"
+#include "fdc.h"
+#include "ide.h"
+#include "io.h"
+#include "lpt.h"
+#include "serial.h"
+
+static struct
+{
+ int reg_idx;
+ uint8_t regs[256];
+} acc3221;
+
+#define REG_BE_LPT1_DISABLE (1 << 4)
+
+#define REG_DB_SERIAL1_DISABLE (1 << 4)
+#define REG_DB_SERIAL2_DISABLE (1 << 1)
+
+#define REG_DE_SIRQ3_SOURCE (3 << 6)
+#define REG_DE_SIRQ3_SERIAL1 (1 << 6)
+#define REG_DE_SIRQ3_SERIAL2 (3 << 6)
+
+#define REG_DE_SIRQ4_SOURCE (3 << 4)
+#define REG_DE_SIRQ4_SERIAL1 (1 << 4)
+#define REG_DE_SIRQ4_SERIAL2 (3 << 4)
+
+#define REG_FB_FDC_DISABLE (1 << 1)
+
+#define REG_FE_IDE_DISABLE (1 << 1)
+
+static void acc3221_write(uint16_t addr, uint8_t val, void *p)
+{
+ if (!(addr & 1))
+ acc3221.reg_idx = val;
+ else
+ {
+ acc3221.regs[acc3221.reg_idx] = val;
+// pclog("Write ACC2036 R%02x %02x %04x:%04x %i\n", acc2036.reg_idx, val, CS,cpu_state.pc, ins);
+
+ if (acc3221.reg_idx >= 0xbc)
+ {
+// pclog("Write ACC3221 R%02x %02x %04x:%04x %i\n", acc3221.reg_idx, val, CS,cpu_state.pc, ins);
+ fdc_remove();
+ if (!(acc3221.regs[0xfb] & REG_FB_FDC_DISABLE))
+ fdc_add();
+
+ serial1_remove();
+ if (!(acc3221.regs[0xdb] & REG_DB_SERIAL1_DISABLE))
+ {
+ uint16_t addr = (acc3221.regs[0xdc] & 0x7f) << 2;
+
+ if ((acc3221.regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL1)
+ {
+// pclog("COM1 addr %03x IRQ 3\n", addr);
+ serial1_set(addr, 3);
+ }
+ else if ((acc3221.regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ4_SERIAL1)
+ {
+// pclog("COM1 addr %03x IRQ 4\n", addr);
+ serial1_set(addr, 4);
+ }
+// else
+// pclog("COM1 addr %03x no IRQ\n", addr);
+ }
+// else
+// pclog("COM1 disabled\n");
+
+ serial2_remove();
+ if (!(acc3221.regs[0xdb] & REG_DB_SERIAL2_DISABLE))
+ {
+ uint16_t addr = (acc3221.regs[0xdd] & 0x7f) << 2;
+
+ if ((acc3221.regs[0xde] & REG_DE_SIRQ3_SOURCE) == REG_DE_SIRQ3_SERIAL2)
+ {
+// pclog("COM2 addr %03x IRQ 3\n", addr);
+ serial2_set(addr, 3);
+ }
+ else if ((acc3221.regs[0xde] & REG_DE_SIRQ4_SOURCE) == REG_DE_SIRQ4_SERIAL2)
+ {
+// pclog("COM2 addr %03x IRQ 4\n", addr);
+ serial2_set(addr, 4);
+ }
+// else
+// pclog("COM2 addr %03x no IRQ\n", addr);
+ }
+// else
+// pclog("COM2 disabled\n");
+
+ lpt1_remove();
+ lpt2_remove();
+ if (!(acc3221.regs[0xbe] & REG_BE_LPT1_DISABLE))
+ {
+// pclog("LPT1 addr %03x\n", acc3221.regs[0xbf] << 2);
+ lpt1_init(acc3221.regs[0xbf] << 2);
+ }
+// else
+// pclog("LPT1 disabled\n");
+
+ ide_pri_disable();
+ if (!(acc3221.regs[0xfe] & REG_FE_IDE_DISABLE))
+ ide_pri_enable();
+ }
+ }
+}
+
+static uint8_t acc3221_read(uint16_t addr, void *p)
+{
+ if (!(addr & 1))
+ return acc3221.reg_idx;
+
+ if (acc3221.reg_idx < 0xbc)
+ return 0xff;
+
+ return acc3221.regs[acc3221.reg_idx];
+}
+
+void acc3221_init()
+{
+ memset(&acc3221, 0, sizeof(acc3221));
+ io_sethandler(0x00f2, 0x0002, acc3221_read, NULL, NULL, acc3221_write, NULL, NULL, NULL);
+}
diff --git a/src/acc3221.h b/src/acc3221.h
new file mode 100644
index 0000000..95824ec
--- /dev/null
+++ b/src/acc3221.h
@@ -0,0 +1 @@
+void acc3221_init();
diff --git a/src/amstrad.c b/src/amstrad.c
index 8817229..714380c 100644
--- a/src/amstrad.c
+++ b/src/amstrad.c
@@ -5,11 +5,14 @@
#include "lpt.h"
#include "mouse.h"
#include "video.h"
+#include "fdc.h"
+#include "x86.h"
#include "amstrad.h"
static uint8_t amstrad_dead;
int amstrad_latch = 0;
+static uint8_t amstrad_language;
uint8_t amstrad_read(uint16_t port, void *priv)
{
@@ -21,16 +24,19 @@ uint8_t amstrad_read(uint16_t port, void *priv)
case 0x378:
return lpt1_read(port, NULL);
case 0x379:
- return lpt1_read(port, NULL) | 7;
+ return lpt1_read(port, NULL) | (amstrad_language & 7);
case 0x37a:
temp = lpt1_read(port, NULL) & 0x1f;
if (romset == ROM_PC1512) return temp | 0x20;
- if (romset == ROM_PC200)
+ if (romset == ROM_PC200 || romset == ROM_PPC512)
{
+ if (fdc_discchange_read())
+ temp |= 0x20;
+/* DIP switches 4,5: Initial video mode */
if (video_is_cga())
- temp |= 0x80;
+ temp |= 0x80; /* CGA 80 */
else if (video_is_mda())
- temp |= 0xc0;
+ temp |= 0xc0; /* MDA */
return temp;
}
if (romset == ROM_PC1640)
@@ -55,8 +61,13 @@ uint8_t amstrad_read(uint16_t port, void *priv)
}
return temp;
case 0x3de:
- return 0x20; /*PC200 - use external video. If internal video is being used
- then this port is handled in vid_pc200.c*/
+ if (romset == ROM_PC200 || romset == ROM_PPC512)
+ {
+/* Read DIP switches / internal display adapter status. This code is only
+ * reached if the IDA is disabled; if it is enabled this read will be
+ * handled by the video card */
+ }
+ return 0x20; /* Disable IDA */
case 0xdead:
return amstrad_dead;
}
@@ -67,6 +78,10 @@ void amstrad_write(uint16_t port, uint8_t val, void *priv)
{
switch (port)
{
+ case 0x66:
+ softresetx86();
+ break;
+
case 0x378:
case 0x379:
case 0x37a:
@@ -151,8 +166,170 @@ void amstrad_init()
io_sethandler(0x0078, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL, NULL);
io_sethandler(0x007a, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL, NULL);
+ io_sethandler(0x0066, 0x0001, NULL, NULL, NULL, amstrad_write, NULL, NULL, NULL);
io_sethandler(0x0378, 0x0003, amstrad_read, NULL, NULL, amstrad_write, NULL, NULL, NULL);
io_sethandler(0xdead, 0x0001, amstrad_read, NULL, NULL, amstrad_write, NULL, NULL, NULL);
- if (romset == ROM_PC200 && gfxcard != GFX_BUILTIN)
+ if ((romset == ROM_PC200 || romset == ROM_PPC512) && gfxcard != GFX_BUILTIN)
io_sethandler(0x03de, 0x0001, amstrad_read, NULL, NULL, amstrad_write, NULL, NULL, NULL);
+
+
}
+
+static void *ams1512_init()
+{
+ amstrad_language = device_get_config_int("language");
+ return &amstrad_language;
+}
+
+device_config_t ams1512_config[] =
+{
+ {
+ .name = "language",
+ .description = "BIOS language",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "English",
+ .value = 7
+ },
+ {
+ .description = "German",
+ .value = 6
+ },
+ {
+ .description = "French",
+ .value = 5
+ },
+ {
+ .description = "Spanish",
+ .value = 4
+ },
+ {
+ .description = "Danish",
+ .value = 3
+ },
+ {
+ .description = "Swedish",
+ .value = 2
+ },
+ {
+ .description = "Italian",
+ .value = 1
+ },
+ {
+ .description = "Diagnostic mode",
+ .value = 0
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 7
+ },
+ {
+ .type = -1
+ }
+};
+
+
+device_config_t ams2086_config[] =
+{
+ {
+ .name = "language",
+ .description = "BIOS language",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "English",
+ .value = 7
+ },
+ {
+ .description = "Diagnostic mode",
+ .value = 0
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 7
+ },
+ {
+ .type = -1
+ }
+};
+
+
+
+device_config_t ams3086_config[] =
+{
+ {
+ .name = "language",
+ .description = "BIOS language",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "English",
+ .value = 7
+ },
+ {
+ .description = "Diagnostic mode",
+ .value = 3
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 7
+ },
+ {
+ .type = -1
+ }
+};
+
+
+
+
+device_t ams1512_device =
+{
+ "Amstrad PC1512 (BIOS)",
+ 0,
+ ams1512_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ams1512_config
+};
+
+
+
+device_t ams2086_device =
+{
+ "Amstrad PC2086 (BIOS)",
+ 0,
+ ams1512_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ams2086_config
+};
+
+
+device_t ams3086_device =
+{
+ "Amstrad PC3086 (BIOS)",
+ 0,
+ ams1512_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ams3086_config
+};
diff --git a/src/amstrad.h b/src/amstrad.h
index bc13c37..0c54fcb 100644
--- a/src/amstrad.h
+++ b/src/amstrad.h
@@ -1,10 +1,15 @@
#include "mouse.h"
+#include "device.h"
void amstrad_init();
extern mouse_t mouse_amstrad;
extern int amstrad_latch;
+extern device_t ams1512_device;
+extern device_t ams2086_device;
+extern device_t ams3086_device;
+
enum
{
AMSTRAD_NOLATCH,
diff --git a/src/cassette.c b/src/cassette.c
new file mode 100644
index 0000000..68f495a
--- /dev/null
+++ b/src/cassette.c
@@ -0,0 +1,187 @@
+/************************************************************************
+
+ PCem: IBM 5150 Cassette support
+
+ Copyright (C) 2019 John Elliott
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*************************************************************************/
+
+#include
+#include "ibm.h"
+#include "cpu.h"
+#include "x86.h"
+#include "device.h"
+#include "pzx.h"
+
+char cassettefn[256];
+
+typedef struct cassette_t
+{
+ uint8_t motor; /* Motor status */
+ pzxfile_t pzx;
+ int cycles_last; /* Cycle count at last cassette poll */
+
+} cassette_t;
+
+extern device_t cassette_device;
+
+
+static cassette_t *st_cas;
+
+
+
+#define CAS_LOG(x) pclog x
+// #define CAS_LOG(x)
+
+
+/* The PCem CPU uses IBM cycles (4.77MHz). PZX uses Spectrum cycles (3.5MHz)
+ * so scale accordingly. */
+static int32_t pzx_cycles(int32_t pc)
+{
+ double d = pc;
+
+ return (int32_t)(((d * 3.5) / 4.772728) + 0.5);
+}
+
+void cassette_eject(void)
+{
+ if (st_cas->pzx.input)
+ {
+ pzx_close(&st_cas->pzx);
+ }
+ cassettefn[0] = 0;
+}
+
+void cassette_load(const char *filename)
+{
+ FILE *fp;
+ unsigned char magic[8];
+
+ if (!filename) return;
+
+ fp = fopen(filename, "rb");
+ if (!fp)
+ {
+ /* Warn user? */
+ CAS_LOG(("Failed to open cassette input %s\n", filename));
+ return;
+ }
+ memset(magic, 0, sizeof(magic));
+ fread(magic, 1, sizeof(magic), fp);
+
+ /* Check for PZX signature. In due course support could be added for
+ * other formats like TZX */
+ if (!memcmp(magic, "PZXT", 4))
+ {
+ const char *result;
+
+ result = pzx_open(&st_cas->pzx, fp);
+
+ if (result)
+ {
+ CAS_LOG(("Failed to open %s as PZX: %s\n",
+ filename, result));
+ fclose(fp);
+ return;
+ }
+ strcpy(cassettefn, filename);
+ }
+}
+
+
+uint8_t cassette_input(void)
+{
+ int ticks;
+
+ /* While motor is off, result is loopback */
+ if (!st_cas->motor)
+ {
+ return ppispeakon;
+ }
+ /* If there is no tapefile open don't try to extract data */
+ if (st_cas->pzx.input == NULL) return 0;
+ /* Otherwise see how many ticks there have been since the last input */
+ if (st_cas->cycles_last == -1)
+ {
+ st_cas->cycles_last = cycles;
+ }
+ if (cycles <= st_cas->cycles_last)
+ {
+ ticks = (st_cas->cycles_last - cycles);
+ }
+ else
+ {
+ ticks = (st_cas->cycles_last + (cpu_get_speed() / 100) - cycles);
+ }
+ st_cas->cycles_last = cycles;
+
+ return pzx_advance(&st_cas->pzx, pzx_cycles(ticks));
+}
+
+
+
+void cassette_set_motor(uint8_t on)
+{
+ if (on && !st_cas->motor)
+ {
+ CAS_LOG(("Start cassette motor\n"));
+ st_cas->cycles_last = -1;
+ }
+ if (st_cas->motor && !on)
+ {
+ CAS_LOG(("Stop cassette motor\n"));
+ st_cas->cycles_last = -1;
+ }
+ st_cas->motor = on;
+}
+
+
+static void *cassette_init(void)
+{
+ cassette_t *cas = malloc(sizeof(cassette_t));
+
+ memset(cas, 0, sizeof(cassette_t));
+ pzx_init(&cas->pzx);
+
+ st_cas = cas;
+ return cas;
+}
+
+
+static void cassette_close(void *p)
+{
+ cassette_t *cas = (cassette_t *)p;
+
+ pzx_close(&cas->pzx);
+
+ free(cas);
+}
+
+
+device_t cassette_device =
+{
+ "Cassette",
+ 0,
+ cassette_init,
+ cassette_close,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
diff --git a/src/cassette.h b/src/cassette.h
new file mode 100644
index 0000000..de77354
--- /dev/null
+++ b/src/cassette.h
@@ -0,0 +1,30 @@
+/************************************************************************
+
+ PCem: IBM 5150 cassette support
+
+ Copyright (C) 2019 John Elliott
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*************************************************************************/
+
+extern device_t cassette_device;
+
+uint8_t cassette_input(void);
+void cassette_set_motor(uint8_t on);
+void cassette_eject(void);
+void cassette_load(const char *filename);
+
+extern char cassettefn[256];
diff --git a/src/cdrom-ioctl.c b/src/cdrom-ioctl.c
index 3ae7a23..8c8eb2b 100644
--- a/src/cdrom-ioctl.c
+++ b/src/cdrom-ioctl.c
@@ -451,8 +451,8 @@ static int ioctl_readsector(uint8_t *b, int sector, int count)
status = ReadFile(hIOCTL, b, count*2048, (LPDWORD)&size, NULL);
ioctl_close();
- /*If the read failed, try again using SPTI*/
- if (!status || size != count*2048)
+ /*If the read 'succeeded' but didn't read all required data, try again using SPTI*/
+ if (status && size != count*2048)
{
uint8_t cmd[12] = { 0xbe, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 };
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
diff --git a/src/codegen.c b/src/codegen.c
index 06f6213..373c15c 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -22,17 +22,19 @@ static struct
x86seg *op_ea_seg;
uint32_t op_32;
int first_uop;
+ int TOP;
} codegen_instructions[MAX_INSTRUCTION_COUNT];
-int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction)
+int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP)
{
int c;
- for (c = 0; c < block->ins; c++)
+ for (c = 0; c <= block->ins; c++)
{
if (codegen_instructions[c].pc == pc)
{
*first_instruction = c;
+ *TOP = codegen_instructions[c].TOP;
return codegen_instructions[c].first_uop;
}
}
@@ -366,7 +368,7 @@ static uint8_t opcode_modrm[256] =
static uint8_t opcode_0f_modrm[256] =
{
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*00*/
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/
1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*30*/
@@ -590,6 +592,7 @@ generate_call:
codegen_instructions[block->ins].op_ssegs = last_op_ssegs;
codegen_instructions[block->ins].op_ea_seg = last_op_ea_seg;
codegen_instructions[block->ins].op_32 = last_op_32;
+ codegen_instructions[block->ins].TOP = cpu_state.TOP;
codegen_instructions[block->ins].first_uop = ir->wr_pos;
codegen_timing_opcode(opcode, fetchdat, op_32, op_pc);
diff --git a/src/codegen.h b/src/codegen.h
index 0f246b3..83f37ae 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -374,7 +374,9 @@ extern codegen_timing_t codegen_timing_686;
extern codegen_timing_t codegen_timing_486;
extern codegen_timing_t codegen_timing_winchip;
extern codegen_timing_t codegen_timing_winchip2;
+extern codegen_timing_t codegen_timing_cyrixiii;
extern codegen_timing_t codegen_timing_k6;
+extern codegen_timing_t codegen_timing_p6;
void codegen_timing_set(codegen_timing_t *timing);
@@ -404,7 +406,7 @@ extern int codegen_in_recompile;
void codegen_generate_reset();
-int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction);
+int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP);
void codegen_set_loop_start(struct ir_data_t *ir, int first_instruction);
#ifdef DEBUG_EXTRA
diff --git a/src/codegen_allocator.c b/src/codegen_allocator.c
index 4b4ffd7..a5301d1 100644
--- a/src/codegen_allocator.c
+++ b/src/codegen_allocator.c
@@ -1,6 +1,7 @@
#if defined(__linux__) || defined(__APPLE__)
#include
#include
+#include
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include
@@ -29,6 +30,10 @@ void codegen_allocator_init()
#if defined WIN32 || defined _WIN32 || defined _WIN32
mem_block_alloc = VirtualAlloc(NULL, MEM_BLOCK_NR * MEM_BLOCK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ /* TODO: check deployment target: older Intel-based versions of macOS don't play
+ nice with MAP_JIT. */
+#elif defined(__APPLE__) && defined(MAP_JIT)
+ mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE|MAP_JIT, 0, 0);
#else
mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 0);
#endif
diff --git a/src/codegen_backend.h b/src/codegen_backend.h
index 7a5c5c0..45668df 100644
--- a/src/codegen_backend.h
+++ b/src/codegen_backend.h
@@ -1,3 +1,6 @@
+#ifndef _CODEGEN_BACKEND_H_
+#define _CODEGEN_BACKEND_H_
+
//#ifdef __amd64__
//#include "codegen_x86-64.h"
#if defined __amd64__
@@ -25,5 +28,16 @@ typedef int (*uOpFn)(codeblock_t *codeblock, struct uop_t *uop);
extern const uOpFn uop_handlers[];
-extern int codegen_host_reg_list[CODEGEN_HOST_REGS];
-extern int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS];
+/*Register will not be preserved across function calls*/
+#define HOST_REG_FLAG_VOLATILE (1 << 0)
+
+typedef struct host_reg_def_t
+{
+ int reg;
+ int flags;
+} host_reg_def_t;
+
+extern host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS];
+extern host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS];
+
+#endif
diff --git a/src/codegen_backend_arm.c b/src/codegen_backend_arm.c
index 0c1c2c8..aa9345c 100644
--- a/src/codegen_backend_arm.c
+++ b/src/codegen_backend_arm.c
@@ -38,27 +38,27 @@ void *codegen_fp_round;
void *codegen_gpf_rout;
void *codegen_exit_rout;
-int codegen_host_reg_list[CODEGEN_HOST_REGS] =
+host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] =
{
- REG_R4,
- REG_R5,
- REG_R6,
- REG_R7,
- REG_R8,
- REG_R9,
- REG_R11,
+ {REG_R4, 0},
+ {REG_R5, 0},
+ {REG_R6, 0},
+ {REG_R7, 0},
+ {REG_R8, 0},
+ {REG_R9, 0},
+ {REG_R11, 0}
};
-int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
+host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
- REG_D8,
- REG_D9,
- REG_D10,
- REG_D11,
- REG_D12,
- REG_D13,
- REG_D14,
- REG_D15
+ {REG_D8, 0},
+ {REG_D9, 0},
+ {REG_D10, 0},
+ {REG_D11, 0},
+ {REG_D12, 0},
+ {REG_D13, 0},
+ {REG_D14, 0},
+ {REG_D15, 0}
};
static void build_load_routine(codeblock_t *block, int size, int is_float)
diff --git a/src/codegen_backend_arm64.c b/src/codegen_backend_arm64.c
index eb50aa6..1885e61 100644
--- a/src/codegen_backend_arm64.c
+++ b/src/codegen_backend_arm64.c
@@ -39,30 +39,30 @@ void *codegen_fp_round_quad;
void *codegen_gpf_rout;
void *codegen_exit_rout;
-int codegen_host_reg_list[CODEGEN_HOST_REGS] =
+host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] =
{
- REG_X19,
- REG_X20,
- REG_X21,
- REG_X22,
- REG_X23,
- REG_X24,
- REG_X25,
- REG_X26,
- REG_X27,
- REG_X28
+ {REG_X19, 0},
+ {REG_X20, 0},
+ {REG_X21, 0},
+ {REG_X22, 0},
+ {REG_X23, 0},
+ {REG_X24, 0},
+ {REG_X25, 0},
+ {REG_X26, 0},
+ {REG_X27, 0},
+ {REG_X28, 0}
};
-int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
+host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
- REG_V8,
- REG_V9,
- REG_V10,
- REG_V11,
- REG_V12,
- REG_V13,
- REG_V14,
- REG_V15
+ {REG_V8, 0},
+ {REG_V9, 0},
+ {REG_V10, 0},
+ {REG_V11, 0},
+ {REG_V12, 0},
+ {REG_V13, 0},
+ {REG_V14, 0},
+ {REG_V15, 0}
};
static void build_load_routine(codeblock_t *block, int size, int is_float)
diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c
index 0cad9bb..73623f0 100644
--- a/src/codegen_backend_arm64_uops.c
+++ b/src/codegen_backend_arm64_uops.c
@@ -839,8 +839,9 @@ static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop)
host_arm64_branch_set_offset(branch_ptr, &block->data[block_pos]);
- host_arm64_STR_IMM_W(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[0] - (uintptr_t)&cpu_state);
- host_arm64_STR_IMM_W(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[4] - (uintptr_t)&cpu_state);
+ host_arm64_mov_imm(block, REG_TEMP, 0x01010101);
+ host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[0] - (uintptr_t)&cpu_state);
+ host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[4] - (uintptr_t)&cpu_state);
host_arm64_STR_IMM_W(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state);
host_arm64_STRB_IMM(block, REG_WZR, REG_CPUSTATE, (uintptr_t)&cpu_state.ismmx - (uintptr_t)&cpu_state);
diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c
index 12c2eb9..19706cd 100644
--- a/src/codegen_backend_arm_uops.c
+++ b/src/codegen_backend_arm_uops.c
@@ -910,9 +910,10 @@ static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop)
*branch_ptr |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2;
- host_arm_MOV_IMM(block, REG_TEMP, 0);
+ host_arm_MOV_IMM(block, REG_TEMP, 0x01010101);
host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[0] - (uintptr_t)&cpu_state);
host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[4] - (uintptr_t)&cpu_state);
+ host_arm_MOV_IMM(block, REG_TEMP, 0);
host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state);
host_arm_STRB_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.ismmx - (uintptr_t)&cpu_state);
diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c
index f1dcd86..a214b69 100644
--- a/src/codegen_backend_x86-64.c
+++ b/src/codegen_backend_x86-64.c
@@ -13,6 +13,7 @@
#if defined(__linux__) || defined(__APPLE__)
#include
#include
+#include
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include
@@ -35,22 +36,32 @@ void *codegen_mem_store_double;
void *codegen_gpf_rout;
void *codegen_exit_rout;
-int codegen_host_reg_list[CODEGEN_HOST_REGS] =
+host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] =
{
- REG_EAX,
- REG_EBX,
- REG_EDX
+ /*Note: while EAX and EDX are normally volatile registers under x86
+ calling conventions, the recompiler will explicitly save and restore
+ them across funcion calls*/
+ {REG_EAX, 0},
+ {REG_EBX, 0},
+ {REG_EDX, 0}
};
-int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
+host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
- REG_XMM0,
- REG_XMM1,
- REG_XMM2,
- REG_XMM3,
- REG_XMM4,
- REG_XMM5,
- REG_XMM6
+#if WIN64
+ /*Windows x86-64 calling convention preserves XMM6-XMM15*/
+ {REG_XMM6, 0},
+ {REG_XMM7, 0},
+#else
+ /*System V AMD64 calling convention does not preserve any XMM registers*/
+ {REG_XMM6, HOST_REG_FLAG_VOLATILE},
+ {REG_XMM7, HOST_REG_FLAG_VOLATILE},
+#endif
+ {REG_XMM1, HOST_REG_FLAG_VOLATILE},
+ {REG_XMM2, HOST_REG_FLAG_VOLATILE},
+ {REG_XMM3, HOST_REG_FLAG_VOLATILE},
+ {REG_XMM4, HOST_REG_FLAG_VOLATILE},
+ {REG_XMM5, HOST_REG_FLAG_VOLATILE}
};
static void build_load_routine(codeblock_t *block, int size, int is_float)
@@ -278,12 +289,6 @@ void codegen_backend_init()
{
codeblock_t *block;
int c;
-#if defined(__linux__) || defined(__APPLE__)
- void *start;
- size_t len;
- long pagesize = sysconf(_SC_PAGESIZE);
- long pagemask = ~(pagesize - 1);
-#endif
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
@@ -312,7 +317,7 @@ void codegen_backend_init()
host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
#endif
- host_x86_CALL(block, (uintptr_t)x86gpf);
+ host_x86_CALL(block, (void *)x86gpf);
codegen_exit_rout = &codeblock[block_current].data[block_pos];
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38);
host_x86_POP(block, REG_R15);
@@ -358,6 +363,8 @@ void codegen_backend_prologue(codeblock_t *block)
host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP);
host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, IREG_TOP_diff_stack_offset, REG_EAX);
}
+ if (block->flags & CODEBLOCK_NO_IMMEDIATES)
+ host_x86_MOV64_REG_IMM(block, REG_R12, (uintptr_t)ram);
}
void codegen_backend_epilogue(codeblock_t *block)
diff --git a/src/codegen_backend_x86-64.h b/src/codegen_backend_x86-64.h
index 150c8c8..3339224 100644
--- a/src/codegen_backend_x86-64.h
+++ b/src/codegen_backend_x86-64.h
@@ -10,3 +10,5 @@
#define HASH(l) ((l) & 0x1ffff)
#define BLOCK_MAX 0x3c0
+
+#define CODEGEN_BACKEND_HAS_MOV_IMM
diff --git a/src/codegen_backend_x86-64_defs.h b/src/codegen_backend_x86-64_defs.h
index 95a5294..8856887 100644
--- a/src/codegen_backend_x86-64_defs.h
+++ b/src/codegen_backend_x86-64_defs.h
@@ -1,3 +1,5 @@
+/*RBP = cpu_state + 128
+ R12 = ram (if block->flags & CODEBLOCK_NO_IMMEDIATES)*/
#define REG_AX 0
#define REG_CX 1
#define REG_DX 2
@@ -42,7 +44,7 @@
#define REG_XMM6 6
#define REG_XMM7 7
-#define REG_XMM_TEMP REG_XMM7
+#define REG_XMM_TEMP REG_XMM0
#define CODEGEN_HOST_REGS 3
#define CODEGEN_HOST_FP_REGS 7
diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c
index 48acb73..41a88b2 100644
--- a/src/codegen_backend_x86-64_ops.c
+++ b/src/codegen_backend_x86-64_ops.c
@@ -499,7 +499,7 @@ void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a,
void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
{
- int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
+ int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (offset >= -128 && offset < 127)
{
@@ -517,9 +517,29 @@ void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
codegen_addbyte(block, imm_data);
}
}
+void host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data)
+{
+ int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
+
+ if (offset >= -128 && offset < 127)
+ {
+ codegen_alloc_bytes(block, 6);
+ codegen_addbyte4(block, 0x66, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/
+ codegen_addword(block, imm_data);
+ }
+ else
+ {
+ if ((uintptr_t)p >> 32)
+ fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p);
+ codegen_alloc_bytes(block, 10);
+ codegen_addbyte4(block, 0x66, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/
+ codegen_addlong(block, (uint32_t)(uintptr_t)p);
+ codegen_addword(block, imm_data);
+ }
+}
void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
{
- int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
+ int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (offset >= -128 && offset < 127)
{
@@ -540,7 +560,7 @@ void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg)
{
- int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
+ int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (src_reg & 8)
fatal("host_x86_MOV8_ABS_REG - bad reg\n");
@@ -614,7 +634,7 @@ void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg)
}
void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg)
{
- int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
+ int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (src_reg & 8)
fatal("host_x86_MOV64_ABS_REG - bad reg\n");
@@ -675,8 +695,9 @@ void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_r
void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p)
{
- int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
-
+ int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
+ int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram;
+
if (dst_reg & 8)
fatal("host_x86_MOV8_REG_ABS reg & 8\n");
@@ -691,6 +712,12 @@ void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p)
codegen_addbyte2(block, 0x8a, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/
codegen_addlong(block, offset);
}
+ else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES))
+ {
+ codegen_alloc_bytes(block, 8);
+ codegen_addbyte4(block, 0x41, 0x8a, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/
+ codegen_addlong(block, ram_offset);
+ }
else
{
fatal("host_x86_MOV8_REG_ABS - out of range\n");
@@ -698,7 +725,8 @@ void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p)
}
void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p)
{
- int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
+ int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
+ int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram;
if (dst_reg & 8)
fatal("host_x86_MOV16_REG_ABS reg & 8\n");
@@ -714,15 +742,28 @@ void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p)
codegen_addbyte3(block, 0x66, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/
codegen_addlong(block, offset);
}
+ else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES))
+ {
+ codegen_alloc_bytes(block, 9);
+ codegen_addbyte4(block, 0x66, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3)); /*MOV dst_reg, ram_offset[R12]*/
+ codegen_addbyte(block, 0x24);
+ codegen_addlong(block, ram_offset);
+ }
else
{
fatal("host_x86_MOV16_REG_ABS - out of range\n");
+ codegen_alloc_bytes(block, 10);
+ codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, p*/
+ codegen_addquad(block, (uintptr_t)p);
+ codegen_alloc_bytes(block, 1);
+ codegen_addbyte4(block, 0x66, 0x41, 0x8b, 0x01 | ((dst_reg & 7) << 3)); /*MOV dst_reg, [r9]*/
}
}
void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p)
{
- int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
-
+ int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
+ int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram;
+
if (dst_reg & 8)
fatal("host_x86_MOV32_REG_ABS reg & 8\n");
@@ -737,6 +778,12 @@ void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p)
codegen_addbyte2(block, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/
codegen_addlong(block, offset);
}
+ else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES))
+ {
+ codegen_alloc_bytes(block, 8);
+ codegen_addbyte4(block, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/
+ codegen_addlong(block, ram_offset);
+ }
else
{
fatal("host_x86_MOV32_REG_ABS - out of range\n");
@@ -748,7 +795,7 @@ void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p)
}
void host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p)
{
- int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
+ int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (dst_reg & 8)
fatal("host_x86_MOV64_REG_ABS reg & 8\n");
@@ -914,6 +961,30 @@ void host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset
fatal("MOV64_BASE_OFFSET_REG - offset %i\n", offset);
}
+void host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uint32_t imm_data)
+{
+ if (base_reg & 8)
+ fatal("host_x86_MOV32_BASE_OFFSET_IMM reg & 8\n");
+
+ if (offset >= -128 && offset < 127)
+ {
+ if (base_reg == REG_RSP)
+ {
+ codegen_alloc_bytes(block, 8);
+ codegen_addbyte4(block, 0xc7, 0x40 | base_reg, 0x24, offset);
+ codegen_addlong(block, imm_data);
+ }
+ else
+ {
+ codegen_alloc_bytes(block, 7);
+ codegen_addbyte3(block, 0xc7, 0x40 | base_reg, offset);
+ codegen_addlong(block, imm_data);
+ }
+ }
+ else
+ fatal("MOV32_BASE_OFFSET_IMM - offset %i\n", offset);
+}
+
void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data)
{
if (reg >= 8)
@@ -987,7 +1058,7 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d
codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/
codegen_addlong(block, imm_data);
}
- else if (offset >= -80 || offset < 0x80)
+ else if (offset >= -0x80 && offset < 0x80)
{
codegen_alloc_bytes(block, 8);
codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/
@@ -1062,8 +1133,9 @@ void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg)
void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p)
{
- int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
-
+ int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
+ int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram;
+
if (dst_reg & 8)
fatal("host_x86_MOVZX_REG_ABS_16_8 - bad reg\n");
@@ -1073,6 +1145,13 @@ void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p)
codegen_addbyte(block, 0x66);
codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/
}
+ else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES))
+ {
+ codegen_alloc_bytes(block, 10);
+ codegen_addbyte2(block, 0x66, 0x41);
+ codegen_addbyte4(block, 0x0f, 0xb6, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/
+ codegen_addlong(block, ram_offset);
+ }
else
{
codegen_alloc_bytes(block, 10);
@@ -1085,8 +1164,9 @@ void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p)
}
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p)
{
- int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
-
+ int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
+ int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram;
+
// if (dst_reg & 8)
// fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n");
@@ -1104,6 +1184,16 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p)
codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/
}
}
+ else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES))
+ {
+ if (dst_reg & 8)
+ fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n");
+
+ codegen_alloc_bytes(block, 9);
+ codegen_addbyte(block, 0x41);
+ codegen_addbyte4(block, 0x0f, 0xb6, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/
+ codegen_addlong(block, ram_offset);
+ }
else
{
if (dst_reg & 8)
@@ -1118,8 +1208,9 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p)
}
void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p)
{
- int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
-
+ int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
+ int64_t ram_offset = (uintptr_t)p - (uintptr_t)ram;
+
if (dst_reg & 8)
fatal("host_x86_MOVZX_REG_ABS_32_16 - bad reg\n");
@@ -1128,6 +1219,13 @@ void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p)
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/
}
+ else if ((ram_offset < (1ull << 32)) && (block->flags & CODEBLOCK_NO_IMMEDIATES))
+ {
+ codegen_alloc_bytes(block, 9);
+ codegen_addbyte(block, 0x41);
+ codegen_addbyte4(block, 0x0f, 0xb7, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOVZX dst_reg, ram_offset[R12]*/
+ codegen_addlong(block, ram_offset);
+ }
else
{
codegen_alloc_bytes(block, 10);
diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h
index 3cd86fb..e1db22a 100644
--- a/src/codegen_backend_x86-64_ops.h
+++ b/src/codegen_backend_x86-64_ops.h
@@ -56,6 +56,7 @@ void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int sr
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
+void host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data);
void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg);
@@ -72,6 +73,8 @@ void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg
void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg);
void host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg);
+void host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uint32_t imm_data);
+
void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p);
diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c
index 729e4fd..b2ca7dc 100644
--- a/src/codegen_backend_x86-64_uops.c
+++ b/src/codegen_backend_x86-64_uops.c
@@ -195,9 +195,9 @@ static int codegen_CALL_FUNC(codeblock_t *block, uop_t *uop)
static int codegen_CALL_FUNC_RESULT(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
- int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
#ifdef RECOMPILER_DEBUG
+ int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
if (!REG_IS_L(dest_size))
fatal("CALL_FUNC_RESULT %02x\n", uop->dest_reg_a_real);
#endif
@@ -826,8 +826,8 @@ static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop)
host_x86_CALL(block, x86_int);
host_x86_JMP(block, codegen_exit_rout);
*branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4;
- host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0);
- host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0);
+ host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0x01010101);
+ host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0x01010101);
host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0);
host_x86_MOV8_ABS_IMM(block, &cpu_state.ismmx, 1);
@@ -918,9 +918,9 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop)
static int codegen_LOAD_SEG(codeblock_t *block, uop_t *uop)
{
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
- int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
#ifdef RECOMPILER_DEBUG
+ int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
if (!REG_IS_W(src_size))
fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p);
#endif
@@ -1029,9 +1029,9 @@ static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop)
static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
- int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
#ifdef RECOMPILER_DEBUG
+ int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
if (!REG_IS_D(dest_size))
fatal("MEM_LOAD_SINGLE - %02x\n", uop->dest_reg_a_real);
#endif
@@ -1048,9 +1048,9 @@ static int codegen_MEM_LOAD_SINGLE(codeblock_t *block, uop_t *uop)
static int codegen_MEM_LOAD_DOUBLE(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
- int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
#ifdef RECOMPILER_DEBUG
+ int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
if (!REG_IS_D(dest_size))
fatal("MEM_LOAD_DOUBLE - %02x\n", uop->dest_reg_a_real);
#endif
@@ -1174,9 +1174,9 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop)
static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop)
{
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real);
- int src_size = IREG_GET_SIZE(uop->src_reg_c_real);
#ifdef RECOMPILER_DEBUG
+ int src_size = IREG_GET_SIZE(uop->src_reg_c_real);
if (!REG_IS_D(src_size))
fatal("MEM_STORE_SINGLE - %02x\n", uop->src_reg_b_real);
#endif
@@ -1193,9 +1193,9 @@ static int codegen_MEM_STORE_SINGLE(codeblock_t *block, uop_t *uop)
static int codegen_MEM_STORE_DOUBLE(codeblock_t *block, uop_t *uop)
{
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real);
- int src_size = IREG_GET_SIZE(uop->src_reg_c_real);
#ifdef RECOMPILER_DEBUG
+ int src_size = IREG_GET_SIZE(uop->src_reg_c_real);
if (!REG_IS_D(src_size))
fatal("MEM_STORE_DOUBLE - %02x\n", uop->src_reg_b_real);
#endif
@@ -1495,7 +1495,7 @@ static int codegen_OR(codeblock_t *block, uop_t *uop)
}
static int codegen_OR_IMM(codeblock_t *block, uop_t *uop)
{
- int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real);
+ int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real);
if (REG_IS_L(dest_size) && REG_IS_L(src_size))
@@ -2766,7 +2766,7 @@ static int codegen_TEST_JS_DEST(codeblock_t *block, uop_t *uop)
static int codegen_XOR(codeblock_t *block, uop_t *uop)
{
- int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
+ int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
@@ -2793,7 +2793,7 @@ static int codegen_XOR(codeblock_t *block, uop_t *uop)
}
static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop)
{
- int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real);
+ int dest_reg = HOST_REG_GET(uop->dest_reg_a_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real);
if (REG_IS_L(dest_size) && REG_IS_L(src_size))
@@ -3141,4 +3141,21 @@ void codegen_set_jump_dest(codeblock_t *block, void *p)
*(uint32_t *)p = (uintptr_t)&block_write_data[block_pos] - ((uintptr_t)p + 4);
}
+void codegen_direct_write_8_imm(codeblock_t *block, void *p, uint8_t imm_data)
+{
+ host_x86_MOV8_ABS_IMM(block, p, imm_data);
+}
+void codegen_direct_write_16_imm(codeblock_t *block, void *p, uint16_t imm_data)
+{
+ host_x86_MOV16_ABS_IMM(block, p, imm_data);
+}
+void codegen_direct_write_32_imm(codeblock_t *block, void *p, uint32_t imm_data)
+{
+ host_x86_MOV32_ABS_IMM(block, p, imm_data);
+}
+void codegen_direct_write_32_imm_stack(codeblock_t *block, int stack_offset, uint32_t imm_data)
+{
+ host_x86_MOV32_BASE_OFFSET_IMM(block, REG_ESP, stack_offset, imm_data);
+}
+
#endif
diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c
index 1700eb0..2fd0565 100644
--- a/src/codegen_backend_x86.c
+++ b/src/codegen_backend_x86.c
@@ -36,21 +36,24 @@ void *codegen_mem_store_double;
void *codegen_gpf_rout;
void *codegen_exit_rout;
-int codegen_host_reg_list[CODEGEN_HOST_REGS] =
+host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] =
{
- REG_EAX,
- REG_EBX,
- REG_EDX
+ /*Note: while EAX and EDX are normally volatile registers under x86
+ calling conventions, the recompiler will explicitly save and restore
+ them across funcion calls*/
+ {REG_EAX, 0},
+ {REG_EBX, 0},
+ {REG_EDX, 0}
};
-int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
+host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
- REG_XMM0,
- REG_XMM1,
- REG_XMM2,
- REG_XMM3,
- REG_XMM4,
- REG_XMM5
+ {REG_XMM0, HOST_REG_FLAG_VOLATILE},
+ {REG_XMM1, HOST_REG_FLAG_VOLATILE},
+ {REG_XMM2, HOST_REG_FLAG_VOLATILE},
+ {REG_XMM3, HOST_REG_FLAG_VOLATILE},
+ {REG_XMM4, HOST_REG_FLAG_VOLATILE},
+ {REG_XMM5, HOST_REG_FLAG_VOLATILE}
};
static void build_load_routine(codeblock_t *block, int size, int is_float)
diff --git a/src/codegen_backend_x86.h b/src/codegen_backend_x86.h
index db521a7..7f9f233 100644
--- a/src/codegen_backend_x86.h
+++ b/src/codegen_backend_x86.h
@@ -10,3 +10,5 @@
#define HASH(l) ((l) & 0x1ffff)
#define BLOCK_MAX 0x3c0
+
+#define CODEGEN_BACKEND_HAS_MOV_IMM
diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c
index 41ab522..7c8a18d 100644
--- a/src/codegen_backend_x86_ops.c
+++ b/src/codegen_backend_x86_ops.c
@@ -445,6 +445,24 @@ void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
codegen_addbyte(block, imm_data);
}
}
+void host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data)
+{
+ int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
+
+ if (offset >= -128 && offset < 127)
+ {
+ codegen_alloc_bytes(block, 6);
+ codegen_addbyte4(block, 0x66, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/
+ codegen_addword(block, imm_data);
+ }
+ else
+ {
+ codegen_alloc_bytes(block, 9);
+ codegen_addbyte3(block, 0x66, 0xc7, 0x05); /*MOV p, imm_data*/
+ codegen_addlong(block, (uint32_t)p);
+ codegen_addword(block, imm_data);
+ }
+}
void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
@@ -701,6 +719,27 @@ void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset
fatal("MOV32_BASE_OFFSET_REG - offset %i\n", offset);
}
+void host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uint32_t imm_data)
+{
+ if (offset >= -128 && offset < 127)
+ {
+ if (base_reg == REG_ESP)
+ {
+ codegen_alloc_bytes(block, 8);
+ codegen_addbyte4(block, 0xc7, 0x40 | base_reg, 0x24, offset);
+ codegen_addlong(block, imm_data);
+ }
+ else
+ {
+ codegen_alloc_bytes(block, 7);
+ codegen_addbyte3(block, 0xc7, 0x40 | base_reg, offset);
+ codegen_addlong(block, imm_data);
+ }
+ }
+ else
+ fatal("MOV32_BASE_OFFSET_IMM - offset %i\n", offset);
+}
+
void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data)
{
codegen_alloc_bytes(block, 2);
@@ -759,7 +798,7 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d
codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/
codegen_addlong(block, imm_data);
}
- else if (offset >= -80 || offset < 0x80)
+ else if (offset >= -0x80 && offset < 0x80)
{
codegen_alloc_bytes(block, 8);
codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/
diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h
index 94f526c..a6ca19f 100644
--- a/src/codegen_backend_x86_ops.h
+++ b/src/codegen_backend_x86_ops.h
@@ -60,6 +60,7 @@ void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int sr
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
+void host_x86_MOV16_ABS_IMM(codeblock_t *block, void *p, uint16_t imm_data);
void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg);
@@ -75,6 +76,8 @@ void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg
void host_x86_MOV16_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int dst_reg);
void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int dst_reg);
+void host_x86_MOV32_BASE_OFFSET_IMM(codeblock_t *block, int base_reg, int offset, uint32_t imm_data);
+
void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p);
diff --git a/src/codegen_backend_x86_ops_sse.c b/src/codegen_backend_x86_ops_sse.c
index dc20d34..50ec638 100644
--- a/src/codegen_backend_x86_ops_sse.c
+++ b/src/codegen_backend_x86_ops_sse.c
@@ -200,7 +200,7 @@ void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/
codegen_addbyte(block, 0x24);
}
- else if (offset >= -80 || offset < 0x80)
+ else if (offset >= -0x80 && offset < 0x80)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/
@@ -429,6 +429,13 @@ void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
}
+void host_x86_PSHUFD_XREG_XREG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t shuffle)
+{
+ codegen_alloc_bytes(block, 5);
+ codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | src_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
+ codegen_addbyte(block, shuffle);
+}
+
void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
@@ -520,27 +527,6 @@ void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/
}
-void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
-{
- codegen_alloc_bytes(block, 9);
- codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/
- codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
- codegen_addbyte(block, 0xee);
-}
-void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
-{
- codegen_alloc_bytes(block, 9);
- codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/
- codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
- codegen_addbyte(block, 0xee);
-}
-void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
-{
- codegen_alloc_bytes(block, 9);
- codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/
- codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
- codegen_addbyte(block, 0xee);
-}
void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
diff --git a/src/codegen_backend_x86_ops_sse.h b/src/codegen_backend_x86_ops_sse.h
index 596f361..e8afdcb 100644
--- a/src/codegen_backend_x86_ops_sse.h
+++ b/src/codegen_backend_x86_ops_sse.h
@@ -88,6 +88,8 @@ void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
+void host_x86_PSHUFD_XREG_XREG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t shuffle);
+
void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
@@ -96,9 +98,6 @@ void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
-void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
-void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
-void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c
index c09512e..94092c3 100644
--- a/src/codegen_backend_x86_uops.c
+++ b/src/codegen_backend_x86_uops.c
@@ -827,8 +827,8 @@ static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop)
host_x86_CALL(block, x86_int);
host_x86_JMP(block, codegen_exit_rout);
*branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4;
- host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0);
- host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0);
+ host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0x01010101);
+ host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0x01010101);
host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0);
host_x86_MOV8_ABS_IMM(block, &cpu_state.ismmx, 1);
@@ -2250,7 +2250,8 @@ static int codegen_PUNPCKHBW(codeblock_t *block, uop_t *uop)
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
{
- host_x86_PUNPCKHBW_XREG_XREG(block, dest_reg, src_reg_b);
+ host_x86_PUNPCKLBW_XREG_XREG(block, dest_reg, src_reg_b);
+ host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/
}
#ifdef RECOMPILER_DEBUG
else
@@ -2265,7 +2266,8 @@ static int codegen_PUNPCKHWD(codeblock_t *block, uop_t *uop)
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
{
- host_x86_PUNPCKHWD_XREG_XREG(block, dest_reg, src_reg_b);
+ host_x86_PUNPCKLWD_XREG_XREG(block, dest_reg, src_reg_b);
+ host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/
}
#ifdef RECOMPILER_DEBUG
else
@@ -2280,7 +2282,8 @@ static int codegen_PUNPCKHDQ(codeblock_t *block, uop_t *uop)
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
{
- host_x86_PUNPCKHDQ_XREG_XREG(block, dest_reg, src_reg_b);
+ host_x86_PUNPCKLDQ_XREG_XREG(block, dest_reg, src_reg_b);
+ host_x86_PSHUFD_XREG_XREG_IMM(block, dest_reg, dest_reg, 0xee); /*0xee = move top 64-bits to low 64-bits*/
}
#ifdef RECOMPILER_DEBUG
else
@@ -2641,6 +2644,11 @@ static int codegen_STORE_PTR_IMM_8(codeblock_t *block, uop_t *uop)
host_x86_MOV8_ABS_IMM(block, uop->p, uop->imm_data);
return 0;
}
+static int codegen_STORE_PTR_IMM_16(codeblock_t *block, uop_t *uop)
+{
+ host_x86_MOV16_ABS_IMM(block, uop->p, uop->imm_data);
+ return 0;
+}
static int codegen_SUB(codeblock_t *block, uop_t *uop)
{
@@ -2836,6 +2844,7 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM,
[UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8,
+ [UOP_STORE_P_IMM_16 & UOP_MASK] = codegen_STORE_PTR_IMM_16,
[UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS,
[UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG,
@@ -3136,4 +3145,21 @@ void codegen_set_jump_dest(codeblock_t *block, void *p)
*(uint32_t *)p = (uintptr_t)&block_write_data[block_pos] - ((uintptr_t)p + 4);
}
+void codegen_direct_write_8_imm(codeblock_t *block, void *p, uint8_t imm_data)
+{
+ host_x86_MOV8_ABS_IMM(block, p, imm_data);
+}
+void codegen_direct_write_16_imm(codeblock_t *block, void *p, uint16_t imm_data)
+{
+ host_x86_MOV16_ABS_IMM(block, p, imm_data);
+}
+void codegen_direct_write_32_imm(codeblock_t *block, void *p, uint32_t imm_data)
+{
+ host_x86_MOV32_ABS_IMM(block, p, imm_data);
+}
+void codegen_direct_write_32_imm_stack(codeblock_t *block, int stack_offset, uint32_t imm_data)
+{
+ host_x86_MOV32_BASE_OFFSET_IMM(block, REG_ESP, stack_offset, imm_data);
+}
+
#endif
diff --git a/src/codegen_backend.c b/src/codegen_block.c
similarity index 95%
rename from src/codegen_backend.c
rename to src/codegen_block.c
index 19e32f6..c8cdc7f 100644
--- a/src/codegen_backend.c
+++ b/src/codegen_block.c
@@ -69,8 +69,10 @@ static int dirty_list_size = 0;
static void block_free_list_add(codeblock_t *block)
{
+#ifndef RELEASE_BUILD
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
fatal("block_free_list_add: block=%p in dirty list\n", block);
+#endif
if (block_free_list)
block->next = block_free_list;
else
@@ -82,8 +84,10 @@ static void block_free_list_add(codeblock_t *block)
static void block_dirty_list_add(codeblock_t *block)
{
+#ifndef RELEASE_BUILD
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
fatal("block_dirty_list_add: block=%p already in dirty list\n", block);
+#endif
// pclog("block_dirty_list_add: block=%i size=%i %i head=%i tail=%i\n", get_block_nr(block), dirty_list_size, dirty_list_check_size(), block_dirty_list_head, block_dirty_list_tail);
if (block_dirty_list_head != BLOCK_INVALID)
{
@@ -108,12 +112,14 @@ static void block_dirty_list_add(codeblock_t *block)
/*Evict oldest block to the free list*/
codeblock_t *evict_block = &codeblock[block_dirty_list_tail];
+#ifndef RELEASE_BUILD
if (!(evict_block->flags & CODEBLOCK_IN_DIRTY_LIST))
fatal("block_dirty_list_add: evict_block=%p %x %x not in dirty list\n", evict_block, evict_block->phys, evict_block->flags);
if (!block_dirty_list_tail)
fatal("block_dirty_list_add - !block_dirty_list_tail\n");
if (evict_block->prev == BLOCK_INVALID)
fatal("block_dirty_list_add - evict_block->prev == BLOCK_INVALID\n");
+#endif
block_dirty_list_tail = evict_block->prev;
codeblock[evict_block->prev].next = BLOCK_INVALID;
@@ -132,8 +138,10 @@ static void block_dirty_list_remove(codeblock_t *block)
codeblock_t *prev_block = &codeblock[block->prev];
codeblock_t *next_block = &codeblock[block->next];
+#ifndef RELEASE_BUILD
if (!(block->flags & CODEBLOCK_IN_DIRTY_LIST))
fatal("block_dirty_list_remove: block=%p not in dirty list\n", block);
+#endif
/*Is block head of list*/
if (block->prev == BLOCK_INVALID)
@@ -148,8 +156,10 @@ static void block_dirty_list_remove(codeblock_t *block)
next_block->prev = block->prev;
dirty_list_size--;
+#ifndef RELEASE_BUILD
if (dirty_list_size < 0)
fatal("remove - dirty_list_size < 0!\n");
+#endif
block->flags &= ~CODEBLOCK_IN_DIRTY_LIST;
// pclog(" block_dirty_list_remove: %p flags = %x\n", block, block->flags);
}
@@ -180,9 +190,10 @@ static codeblock_t *block_free_list_get()
/*Free list is empty, check the dirty list*/
if (block_dirty_list_tail)
{
+#ifndef RELEASE_BUILD
if (dirty_list_size <= 0)
fatal("get - dirty_list_size <= 0!\n");
-
+#endif
/*Reuse oldest block*/
block = &codeblock[block_dirty_list_tail];
@@ -310,9 +321,10 @@ static void add_to_block_list(codeblock_t *block)
uint16_t block_nr = get_block_nr(block);
//pclog("Add to block list %p %08x %llx %x\n", block, block->phys, block->page_mask2, block->flags);
+#ifndef RELEASE_BUILD
if (!block->page_mask)
fatal("add_to_block_list - mask = 0 %llx %llx\n", block->page_mask,block->page_mask2);
-
+#endif
if (block_prev_nr)
{
block->next = block_prev_nr;
@@ -327,8 +339,10 @@ static void add_to_block_list(codeblock_t *block)
if (block->next)
{
+#ifndef RELEASE_BUILD
if (codeblock[block->next].pc == BLOCK_PC_INVALID)
fatal("block->next->pc=BLOCK_PC_INVALID %p %p %x %x\n", (void *)&codeblock[block->next], (void *)codeblock, block_current, block_pos);
+#endif
}
if (block->page_mask2)
@@ -356,9 +370,10 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc)
{
if (!block->page_mask)
return;
+#ifndef RELEASE_BUILD
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
fatal("remove_from_block_list: in dirty list\n");
-
+#endif
if (block->prev)
{
codeblock[block->prev].next = block->next;
@@ -376,8 +391,10 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc)
if (!(block->flags & CODEBLOCK_HAS_PAGE2))
{
+#ifndef RELEASE_BUILD
if (block->prev_2 || block->next_2)
fatal("Invalid block_2 %x %p %08x\n", block->flags, block, block->phys);
+#endif
return;
}
block->flags &= ~CODEBLOCK_HAS_PAGE2;
@@ -404,11 +421,12 @@ static void invalidate_block(codeblock_t *block)
{
uint32_t old_pc = block->pc;
+#ifndef RELEASE_BUILD
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
fatal("invalidate_block: already in dirty list\n");
if (block->pc == BLOCK_PC_INVALID)
fatal("Invalidating deleted block\n");
-
+#endif
remove_from_block_list(block, old_pc);
block_dirty_list_add(block);
if (block->head_mem_block)
@@ -423,8 +441,10 @@ static void delete_block(codeblock_t *block)
if (block == &codeblock[codeblock_hash[HASH(block->phys)]])
codeblock_hash[HASH(block->phys)] = BLOCK_INVALID;
+#ifndef RELEASE_BUILD
if (block->pc == BLOCK_PC_INVALID)
fatal("Deleting deleted block\n");
+#endif
block->pc = BLOCK_PC_INVALID;
codeblock_tree_delete(block);
@@ -443,8 +463,10 @@ static void delete_dirty_block(codeblock_t *block)
if (block == &codeblock[codeblock_hash[HASH(block->phys)]])
codeblock_hash[HASH(block->phys)] = BLOCK_INVALID;
+#ifndef RELEASE_BUILD
if (block->pc == BLOCK_PC_INVALID)
fatal("Deleting deleted block\n");
+#endif
block->pc = BLOCK_PC_INVALID;
codeblock_tree_delete(block);
@@ -494,8 +516,10 @@ void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr)
invalidate_block(block);
cpu_recomp_evicted++;
}
+#ifndef RELEASE_BUILD
if (block_nr == next_block)
fatal("Broken 1\n");
+#endif
block_nr = next_block;
}
@@ -512,8 +536,10 @@ void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr)
invalidate_block(block);
cpu_recomp_evicted++;
}
+#ifndef RELEASE_BUILD
if (block_nr == next_block)
fatal("Broken 2\n");
+#endif
block_nr = next_block;
}
@@ -541,8 +567,10 @@ void codegen_block_init(uint32_t phys_addr)
if (!page->block)
mem_flush_write_page(phys_addr, cs+cpu_state.pc);
block = block_free_list_get();
+#ifndef RELEASE_BUILD
if (!block)
fatal("codegen_block_init: block_free_list_get() returned NULL\n");
+#endif
block_current = get_block_nr(block);
block_num = HASH(phys_addr);
@@ -582,10 +610,10 @@ void codegen_block_start_recompile(codeblock_t *block)
block_num = HASH(block->phys);
block_current = get_block_nr(block);//block->pnt;
-
+#ifndef RELEASE_BUILD
if (block->pc != cs + cpu_state.pc || (block->flags & CODEBLOCK_WAS_RECOMPILED))
fatal("Recompile to used block!\n");
-
+#endif
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
@@ -695,6 +723,7 @@ void codegen_block_generate_end_mask_recompile()
if (!pages[block->phys_2 >> 12].block_2)
mem_flush_write_page(block->phys_2, codegen_endpc);
+#ifndef RELEASE_BUILD
if (!block->page_mask2)
fatal("!page_mask2\n");
if (block->next_2)
@@ -703,6 +732,7 @@ void codegen_block_generate_end_mask_recompile()
if (codeblock[block->next_2].pc == BLOCK_PC_INVALID)
fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]);
}
+#endif
}
else
{
@@ -724,9 +754,10 @@ void codegen_block_generate_end_mask_mark()
uint32_t end_pc;
page_t *p;
+#ifndef RELEASE_BUILD
if (block->flags & CODEBLOCK_BYTE_MASK)
fatal("codegen_block_generate_end_mask2() - BYTE_MASK\n");
-
+#endif
block->page_mask = 0;
start_pc = (block->pc & 0xfff) & ~63;
if ((block->pc ^ codegen_endpc) & ~0xfff)
@@ -771,7 +802,7 @@ void codegen_block_generate_end_mask_mark()
if (!pages[block->phys_2 >> 12].block_2)
mem_flush_write_page(block->phys_2, codegen_endpc);
-
+#ifndef RELEASE_BUILD
if (!block->page_mask2)
fatal("!page_mask2\n");
if (block->next_2)
@@ -780,7 +811,7 @@ void codegen_block_generate_end_mask_mark()
if (codeblock[block->next_2].pc == BLOCK_PC_INVALID)
fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]);
}
-
+#endif
block->dirty_mask2 = &page_2->dirty_mask;
}
else
diff --git a/src/codegen_ir.c b/src/codegen_ir.c
index d7e6157..e42ac49 100644
--- a/src/codegen_ir.c
+++ b/src/codegen_ir.c
@@ -107,37 +107,61 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
if ((uop->type & UOP_MASK) == UOP_INVALID)
continue;
- if (uop->type & UOP_TYPE_PARAMS_REGS)
+#ifdef CODEGEN_BACKEND_HAS_MOV_IMM
+ if ((uop->type & UOP_MASK) == (UOP_MOV_IMM & UOP_MASK) && reg_is_native_size(uop->dest_reg_a) && !codegen_reg_is_loaded(uop->dest_reg_a) && reg_version[IREG_GET_REG(uop->dest_reg_a.reg)][uop->dest_reg_a.version].refcount <= 0)
{
- codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c);
- if (uop->src_reg_a.reg != IREG_INVALID)
- {
- uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL);
- }
- if (uop->src_reg_b.reg != IREG_INVALID)
- {
- uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b, NULL);
- }
- if (uop->src_reg_c.reg != IREG_INVALID)
- {
- uop->src_reg_c_real = codegen_reg_alloc_read_reg(block, uop->src_reg_c, NULL);
- }
+ /*Special case for UOP_MOV_IMM - if destination not already in host register
+ and won't be used again then just store directly to memory*/
+ codegen_reg_write_imm(block, uop->dest_reg_a, uop->imm_data);
}
-
- if (uop->type & UOP_TYPE_ORDER_BARRIER)
- codegen_reg_flush(ir, block);
+ else
+#endif
+ if ((uop->type & UOP_MASK) == (UOP_MOV & UOP_MASK) && reg_version[IREG_GET_REG(uop->src_reg_a.reg)][uop->src_reg_a.version].refcount <= 1 &&
+ reg_is_native_size(uop->src_reg_a) && reg_is_native_size(uop->dest_reg_a))
+ {
+ /*Special case for UOP_MOV - if source register won't be used again then
+ just rename it to dest register instead of moving*/
+ codegen_reg_alloc_register(invalid_ir_reg, uop->src_reg_a, invalid_ir_reg, invalid_ir_reg);
+ uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL);
+ codegen_reg_rename(block, uop->src_reg_a, uop->dest_reg_a);
+ if (uop->type & UOP_TYPE_ORDER_BARRIER)
+ codegen_reg_flush(ir, block);
+ }
+ else
+ {
+ if (uop->type & UOP_TYPE_PARAMS_REGS)
+ {
+ codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c);
+ if (uop->src_reg_a.reg != IREG_INVALID)
+ {
+ uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL);
+ }
+ if (uop->src_reg_b.reg != IREG_INVALID)
+ {
+ uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b, NULL);
+ }
+ if (uop->src_reg_c.reg != IREG_INVALID)
+ {
+ uop->src_reg_c_real = codegen_reg_alloc_read_reg(block, uop->src_reg_c, NULL);
+ }
+ }
- if (uop->type & UOP_TYPE_PARAMS_REGS)
- {
- if (uop->dest_reg_a.reg != IREG_INVALID)
+ if (uop->type & UOP_TYPE_ORDER_BARRIER)
+ codegen_reg_flush(ir, block);
+
+ if (uop->type & UOP_TYPE_PARAMS_REGS)
{
- uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a);
+ if (uop->dest_reg_a.reg != IREG_INVALID)
+ {
+ uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a);
+ }
}
+#ifndef RELEASE_BUILD
+ if (!uop_handlers[uop->type & UOP_MASK])
+ fatal("!uop_handlers[uop->type & UOP_MASK] %08x\n", uop->type);
+#endif
+ uop_handlers[uop->type & UOP_MASK](block, uop);
}
-
- if (!uop_handlers[uop->type & UOP_MASK])
- fatal("!uop_handlers[uop->type & UOP_MASK] %08x\n", uop->type);
- uop_handlers[uop->type & UOP_MASK](block, uop);
if (uop->type & UOP_TYPE_JUMP)
{
diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h
index 76f4979..b1f4b3c 100644
--- a/src/codegen_ir_defs.h
+++ b/src/codegen_ir_defs.h
@@ -55,6 +55,7 @@
/*UOP_JMP_DEST - jump to ptr*/
#define UOP_JMP_DEST (UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x17 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
#define UOP_NOP_BARRIER (UOP_TYPE_BARRIER | 0x18)
+#define UOP_STORE_P_IMM_16 (UOP_TYPE_PARAMS_IMM | 0x19)
#ifdef DEBUG_EXTRA
/*UOP_LOG_INSTR - log non-recompiled instruction in imm_data*/
@@ -765,6 +766,7 @@ static inline void uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, in
#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm)
#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm)
+#define uop_STORE_PTR_IMM_16(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_16, ir, p, imm)
#define uop_TEST_JNS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JNS_DEST, ir, src_reg)
#define uop_TEST_JS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JS_DEST, ir, src_reg)
@@ -807,4 +809,9 @@ void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int
void codegen_set_jump_dest(codeblock_t *block, void *p);
+void codegen_direct_write_8_imm(codeblock_t *block, void *p, uint8_t imm_data);
+void codegen_direct_write_16_imm(codeblock_t *block, void *p, uint16_t imm_data);
+void codegen_direct_write_32_imm(codeblock_t *block, void *p, uint32_t imm_data);
+void codegen_direct_write_32_imm_stack(codeblock_t *block, int stack_offset, uint32_t imm_data);
+
#endif
diff --git a/src/codegen_ops_arith.c b/src/codegen_ops_arith.c
index 08bb5f1..2127c57 100644
--- a/src/codegen_ops_arith.c
+++ b/src/codegen_ops_arith.c
@@ -1953,12 +1953,12 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
break;
case 0x10: /*ADC*/
- get_cf(ir, IREG_temp2);
+ get_cf(ir, IREG_temp3);
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
uop_ADD(ir, IREG_temp1, IREG_temp0, IREG_temp2);
else
uop_ADD_IMM(ir, IREG_temp1, IREG_temp0, imm);
- uop_ADD(ir, IREG_temp1, IREG_temp1, IREG_temp2);
+ uop_ADD(ir, IREG_temp1, IREG_temp1, IREG_temp3);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
uop_MOV(ir, IREG_flags_op1, IREG_temp0);
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
@@ -1970,12 +1970,12 @@ uint32_t rop81_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fet
break;
case 0x18: /*SBB*/
- get_cf(ir, IREG_temp2);
+ get_cf(ir, IREG_temp3);
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
uop_SUB(ir, IREG_temp1, IREG_temp0, IREG_temp2);
else
uop_SUB_IMM(ir, IREG_temp1, IREG_temp0, imm);
- uop_SUB(ir, IREG_temp1, IREG_temp1, IREG_temp2);
+ uop_SUB(ir, IREG_temp1, IREG_temp1, IREG_temp3);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
uop_MOV(ir, IREG_flags_op1, IREG_temp0);
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
diff --git a/src/codegen_ops_fpu_arith.c b/src/codegen_ops_fpu_arith.c
index 3f05802..e3bfb28 100644
--- a/src/codegen_ops_fpu_arith.c
+++ b/src/codegen_ops_fpu_arith.c
@@ -274,6 +274,8 @@ uint32_t ropFADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint
{ \
x86seg *target_seg; \
\
+ if ((cpu_state.npxc >> 10) & 3) \
+ return 0; \
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
diff --git a/src/codegen_ops_helpers.c b/src/codegen_ops_helpers.c
index 903a0e5..896ac29 100644
--- a/src/codegen_ops_helpers.c
+++ b/src/codegen_ops_helpers.c
@@ -34,9 +34,10 @@ int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc,
int start;
int max_unroll;
int first_instruction;
+ int TOP = -1;
/*Check that dest instruction was actually compiled into block*/
- start = codegen_get_instruction_uop(block, dest_addr, &first_instruction);
+ start = codegen_get_instruction_uop(block, dest_addr, &first_instruction, &TOP);
/*Couldn't find any uOPs corresponding to the destination instruction*/
if (start == -1)
@@ -48,8 +49,14 @@ int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc,
return 0;
}
else
+ {
start = ir->wr_pos;
+ TOP = cpu_state.TOP;
+ }
}
+
+ if (TOP != cpu_state.TOP)
+ return 0;
max_unroll = UNROLL_MAX_UOPS / ((ir->wr_pos-start)+6);
if (max_unroll > (UNROLL_MAX_REG_REFERENCES / max_version_refcount))
diff --git a/src/codegen_ops_misc.c b/src/codegen_ops_misc.c
index 13e0e64..4eb5906 100644
--- a/src/codegen_ops_misc.c
+++ b/src/codegen_ops_misc.c
@@ -356,11 +356,11 @@ uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
return -1;
case 0x28: /*JMP far*/
+ uop_MOVZX(ir, IREG_pc, src_reg);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
- uop_LOAD_FUNC_ARG_IMM(ir, 1, cpu_state.oldpc);
+ uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 1);
uop_CALL_FUNC(ir, loadcsjmp);
- uop_MOVZX(ir, IREG_pc, src_reg);
return -1;
case 0x30: /*PUSH*/
@@ -463,11 +463,11 @@ uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
return -1;
case 0x28: /*JMP far*/
+ uop_MOV(ir, IREG_pc, src_reg);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
- uop_LOAD_FUNC_ARG_IMM(ir, 1, cpu_state.oldpc);
+ uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 1);
uop_CALL_FUNC(ir, loadcsjmp);
- uop_MOV(ir, IREG_pc, src_reg);
return -1;
case 0x30: /*PUSH*/
diff --git a/src/codegen_ops_mmx_loadstore.c b/src/codegen_ops_mmx_loadstore.c
index ac591e8..a376f9b 100644
--- a/src/codegen_ops_mmx_loadstore.c
+++ b/src/codegen_ops_mmx_loadstore.c
@@ -38,6 +38,9 @@ uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
{
int src_reg = (fetchdat >> 3) & 7;
+ if (cpu_iscyrix && (cpu_cur_status & CPU_STATUS_SMM))
+ return 0;
+
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
diff --git a/src/codegen_reg.c b/src/codegen_reg.c
index eb07cfb..b8966b9 100644
--- a/src/codegen_reg.c
+++ b/src/codegen_reg.c
@@ -22,7 +22,7 @@ typedef struct host_reg_set_t
{
ir_reg_t *regs;
uint8_t *dirty;
- int *reg_list;
+ host_reg_def_t *reg_list;
uint16_t locked;
int nr_regs;
} host_reg_set_t;
@@ -191,7 +191,7 @@ void codegen_reg_mark_as_required()
}
}
-static int reg_is_native_size(ir_reg_t ir_reg)
+int reg_is_native_size(ir_reg_t ir_reg)
{
int native_size = ireg_data[IREG_GET_REG(ir_reg.reg)].native_size;
int requested_size = IREG_GET_SIZE(ir_reg.reg);
@@ -271,75 +271,91 @@ static void codegen_reg_load(host_reg_set_t *reg_set, codeblock_t *block, int c,
switch (ireg_data[IREG_GET_REG(ir_reg.reg)].native_size)
{
case REG_WORD:
+#ifndef RELEASE_BUILD
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER)
fatal("codegen_reg_load - REG_WORD !REG_INTEGER\n");
+#endif
if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256)
- codegen_direct_read_16_stack(block, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
+ codegen_direct_read_16_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
else
- codegen_direct_read_16(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p);
+ codegen_direct_read_16(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p);
break;
case REG_DWORD:
+#ifndef RELEASE_BUILD
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER)
fatal("codegen_reg_load - REG_DWORD !REG_INTEGER\n");
+#endif
if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256)
- codegen_direct_read_32_stack(block, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
+ codegen_direct_read_32_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
else
- codegen_direct_read_32(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p);
+ codegen_direct_read_32(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p);
break;
case REG_QWORD:
+#ifndef RELEASE_BUILD
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP)
fatal("codegen_reg_load - REG_QWORD !REG_FP\n");
+#endif
if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256)
- codegen_direct_read_64_stack(block, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
+ codegen_direct_read_64_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
else
- codegen_direct_read_64(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p);
+ codegen_direct_read_64(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p);
break;
case REG_POINTER:
+#ifndef RELEASE_BUILD
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER)
fatal("codegen_reg_load - REG_POINTER !REG_INTEGER\n");
+#endif
if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256)
- codegen_direct_read_pointer_stack(block, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
+ codegen_direct_read_pointer_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
else
- codegen_direct_read_pointer(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p);
+ codegen_direct_read_pointer(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p);
break;
case REG_DOUBLE:
+#ifndef RELEASE_BUILD
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP)
fatal("codegen_reg_load - REG_DOUBLE !REG_FP\n");
+#endif
if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256)
- codegen_direct_read_double_stack(block, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
+ codegen_direct_read_double_stack(block, reg_set->reg_list[c].reg, (intptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
else
- codegen_direct_read_double(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p);
+ codegen_direct_read_double(block, reg_set->reg_list[c].reg, ireg_data[IREG_GET_REG(ir_reg.reg)].p);
break;
case REG_FPU_ST_BYTE:
+#ifndef RELEASE_BUILD
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER)
fatal("codegen_reg_load - REG_FPU_ST_BYTE !REG_INTEGER\n");
+#endif
if (block->flags & CODEBLOCK_STATIC_TOP)
- codegen_direct_read_8(block, reg_set->reg_list[c], &cpu_state.tag[ir_reg.reg & 7]);
+ codegen_direct_read_8(block, reg_set->reg_list[c].reg, &cpu_state.tag[ir_reg.reg & 7]);
else
- codegen_direct_read_st_8(block, reg_set->reg_list[c], &cpu_state.tag[0], ir_reg.reg & 7);
+ codegen_direct_read_st_8(block, reg_set->reg_list[c].reg, &cpu_state.tag[0], ir_reg.reg & 7);
break;
case REG_FPU_ST_QWORD:
+#ifndef RELEASE_BUILD
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP)
fatal("codegen_reg_load - REG_FPU_ST_QWORD !REG_FP\n");
+#endif
if (block->flags & CODEBLOCK_STATIC_TOP)
- codegen_direct_read_64(block, reg_set->reg_list[c], &cpu_state.MM[ir_reg.reg & 7]);
+ codegen_direct_read_64(block, reg_set->reg_list[c].reg, &cpu_state.MM[ir_reg.reg & 7]);
else
- codegen_direct_read_st_64(block, reg_set->reg_list[c], &cpu_state.MM[0], ir_reg.reg & 7);
+ codegen_direct_read_st_64(block, reg_set->reg_list[c].reg, &cpu_state.MM[0], ir_reg.reg & 7);
break;
case REG_FPU_ST_DOUBLE:
+#ifndef RELEASE_BUILD
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_FP)
fatal("codegen_reg_load - REG_FPU_ST_DOUBLE !REG_FP\n");
+#endif
if (block->flags & CODEBLOCK_STATIC_TOP)
- codegen_direct_read_double(block, reg_set->reg_list[c], &cpu_state.ST[ir_reg.reg & 7]);
+ codegen_direct_read_double(block, reg_set->reg_list[c].reg, &cpu_state.ST[ir_reg.reg & 7]);
else
- codegen_direct_read_st_double(block, reg_set->reg_list[c], &cpu_state.ST[0], ir_reg.reg & 7);
+ codegen_direct_read_st_double(block, reg_set->reg_list[c].reg, &cpu_state.ST[0], ir_reg.reg & 7);
break;
default:
@@ -363,81 +379,99 @@ static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, i
switch (ireg_data[ir_reg].native_size)
{
case REG_BYTE:
+#ifndef RELEASE_BUILD
if (ireg_data[ir_reg].type != REG_INTEGER)
fatal("codegen_reg_writeback - REG_BYTE !REG_INTEGER\n");
if ((uintptr_t)p < 256)
fatal("codegen_reg_writeback - REG_BYTE %p\n", p);
- codegen_direct_write_8(block, p, reg_set->reg_list[c]);
+#endif
+ codegen_direct_write_8(block, p, reg_set->reg_list[c].reg);
break;
case REG_WORD:
+#ifndef RELEASE_BUILD
if (ireg_data[ir_reg].type != REG_INTEGER)
fatal("codegen_reg_writeback - REG_WORD !REG_INTEGER\n");
if ((uintptr_t)p < 256)
fatal("codegen_reg_writeback - REG_WORD %p\n", p);
- codegen_direct_write_16(block, p, reg_set->reg_list[c]);
+#endif
+ codegen_direct_write_16(block, p, reg_set->reg_list[c].reg);
break;
case REG_DWORD:
+#ifndef RELEASE_BUILD
if (ireg_data[ir_reg].type != REG_INTEGER)
fatal("codegen_reg_writeback - REG_DWORD !REG_INTEGER\n");
+#endif
if ((uintptr_t)p < 256)
- codegen_direct_write_32_stack(block, (int)p, reg_set->reg_list[c]);
+ codegen_direct_write_32_stack(block, (intptr_t)p, reg_set->reg_list[c].reg);
else
- codegen_direct_write_32(block, p, reg_set->reg_list[c]);
+ codegen_direct_write_32(block, p, reg_set->reg_list[c].reg);
break;
case REG_QWORD:
+#ifndef RELEASE_BUILD
if (ireg_data[ir_reg].type != REG_FP)
fatal("codegen_reg_writeback - REG_QWORD !REG_FP\n");
+#endif
if ((uintptr_t)p < 256)
- codegen_direct_write_64_stack(block, (int)p, reg_set->reg_list[c]);
+ codegen_direct_write_64_stack(block, (intptr_t)p, reg_set->reg_list[c].reg);
else
- codegen_direct_write_64(block, p, reg_set->reg_list[c]);
+ codegen_direct_write_64(block, p, reg_set->reg_list[c].reg);
break;
case REG_POINTER:
+#ifndef RELEASE_BUILD
if (ireg_data[ir_reg].type != REG_INTEGER)
fatal("codegen_reg_writeback - REG_POINTER !REG_INTEGER\n");
if ((uintptr_t)p < 256)
fatal("codegen_reg_writeback - REG_POINTER %p\n", p);
- codegen_direct_write_ptr(block, p, reg_set->reg_list[c]);
+#endif
+ codegen_direct_write_ptr(block, p, reg_set->reg_list[c].reg);
break;
case REG_DOUBLE:
+#ifndef RELEASE_BUILD
if (ireg_data[ir_reg].type != REG_FP)
fatal("codegen_reg_writeback - REG_DOUBLE !REG_FP\n");
+#endif
if ((uintptr_t)p < 256)
- codegen_direct_write_double_stack(block, (int)p, reg_set->reg_list[c]);
+ codegen_direct_write_double_stack(block, (intptr_t)p, reg_set->reg_list[c].reg);
else
- codegen_direct_write_double(block, p, reg_set->reg_list[c]);
+ codegen_direct_write_double(block, p, reg_set->reg_list[c].reg);
break;
case REG_FPU_ST_BYTE:
+#ifndef RELEASE_BUILD
if (ireg_data[ir_reg].type != REG_INTEGER)
fatal("codegen_reg_writeback - REG_FPU_ST_BYTE !REG_INTEGER\n");
+#endif
if (block->flags & CODEBLOCK_STATIC_TOP)
- codegen_direct_write_8(block, &cpu_state.tag[reg_set->regs[c].reg & 7], reg_set->reg_list[c]);
+ codegen_direct_write_8(block, &cpu_state.tag[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg);
else
- codegen_direct_write_st_8(block, &cpu_state.tag[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c]);
+ codegen_direct_write_st_8(block, &cpu_state.tag[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg);
break;
case REG_FPU_ST_QWORD:
+#ifndef RELEASE_BUILD
if (ireg_data[ir_reg].type != REG_FP)
fatal("codegen_reg_writeback - REG_FPU_ST_QWORD !REG_FP\n");
+#endif
if (block->flags & CODEBLOCK_STATIC_TOP)
- codegen_direct_write_64(block, &cpu_state.MM[reg_set->regs[c].reg & 7], reg_set->reg_list[c]);
+ codegen_direct_write_64(block, &cpu_state.MM[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg);
else
- codegen_direct_write_st_64(block, &cpu_state.MM[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c]);
+ codegen_direct_write_st_64(block, &cpu_state.MM[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg);
break;
case REG_FPU_ST_DOUBLE:
+#ifndef RELEASE_BUILD
if (ireg_data[ir_reg].type != REG_FP)
fatal("codegen_reg_writeback - REG_FPU_ST_DOUBLE !REG_FP\n");
+#endif
if (block->flags & CODEBLOCK_STATIC_TOP)
- codegen_direct_write_double(block, &cpu_state.ST[reg_set->regs[c].reg & 7], reg_set->reg_list[c]);
+ codegen_direct_write_double(block, &cpu_state.ST[reg_set->regs[c].reg & 7], reg_set->reg_list[c].reg);
else
- codegen_direct_write_st_double(block, &cpu_state.ST[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c]);
+ codegen_direct_write_st_double(block, &cpu_state.ST[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c].reg);
break;
default:
@@ -449,6 +483,49 @@ static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, i
reg_set->dirty[c] = 0;
}
+#ifdef CODEGEN_BACKEND_HAS_MOV_IMM
+void codegen_reg_write_imm(codeblock_t *block, ir_reg_t ir_reg, uint32_t imm_data)
+{
+ int reg_idx = IREG_GET_REG(ir_reg.reg);
+ void *p = ireg_data[reg_idx].p;
+
+ switch (ireg_data[reg_idx].native_size)
+ {
+ case REG_BYTE:
+#ifndef RELEASE_BUILD
+ if ((uintptr_t)p < 256)
+ fatal("codegen_reg_write_imm - REG_BYTE %p\n", p);
+#endif
+ codegen_direct_write_8_imm(block, p, imm_data);
+ break;
+
+ case REG_WORD:
+#ifndef RELEASE_BUILD
+ if ((uintptr_t)p < 256)
+ fatal("codegen_reg_write_imm - REG_WORD %p\n", p);
+#endif
+ codegen_direct_write_16_imm(block, p, imm_data);
+ break;
+
+ case REG_DWORD:
+ if ((uintptr_t)p < 256)
+ codegen_direct_write_32_imm_stack(block, (int)p, imm_data);
+ else
+ codegen_direct_write_32_imm(block, p, imm_data);
+ break;
+
+ case REG_POINTER:
+ case REG_QWORD:
+ case REG_DOUBLE:
+ case REG_FPU_ST_BYTE:
+ case REG_FPU_ST_QWORD:
+ case REG_FPU_ST_DOUBLE:
+ default:
+ fatal("codegen_reg_write_imm - native_size=%i\n", ireg_data[reg_idx].native_size);
+ }
+}
+#endif
+
static void alloc_reg(ir_reg_t ir_reg)
{
host_reg_set_t *reg_set = get_reg_set(ir_reg);
@@ -459,8 +536,10 @@ static void alloc_reg(ir_reg_t ir_reg)
{
if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg))
{
+#ifndef RELEASE_BUILD
if (reg_set->regs[c].version != ir_reg.version)
fatal("alloc_reg - host_regs[c].version != ir_reg.version %i %p %p %i %i\n", c, reg_set, &host_reg_set, reg_set->regs[c].reg, ir_reg.reg);
+#endif
reg_set->locked |= (1 << c);
return;
}
@@ -552,9 +631,10 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, in
reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount++;
break;
}
-
+#ifndef RELEASE_BUILD
if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount)
fatal("codegen_reg_alloc_read_reg - version mismatch!\n");
+#endif
}
if (c == reg_set->nr_regs)
@@ -573,8 +653,10 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, in
if (!(reg_set->locked & (1 << c)))
break;
}
+#ifndef RELEASE_BUILD
if (c == reg_set->nr_regs)
fatal("codegen_reg_alloc_read_reg - out of registers\n");
+#endif
}
if (reg_set->dirty[c])
codegen_reg_writeback(reg_set, block, c, 1);
@@ -589,13 +671,15 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, in
// pclog(" already loaded %i\n", c);
reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount--;
+#ifndef RELEASE_BUILD
if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount == (uint8_t)-1)
fatal("codegen_reg_alloc_read_reg - refcount < 0\n");
+#endif
if (host_reg_idx)
*host_reg_idx = c;
// pclog(" codegen_reg_alloc_read_reg: %i.%i %i %02x.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c], reg_set->regs[c].reg,reg_set->regs[c].version, c);
- return reg_set->reg_list[c] | IREG_GET_SIZE(ir_reg.reg);
+ return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg);
}
ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg)
@@ -614,16 +698,18 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg)
codegen_reg_alloc_read_reg(block, parent_reg, &c);
+#ifndef RELEASE_BUILD
if (IREG_GET_REG(reg_set->regs[c].reg) != IREG_GET_REG(ir_reg.reg) || reg_set->regs[c].version > ir_reg.version-1)
fatal("codegen_reg_alloc_write_reg sub_reg - doesn't match %i %02x.%i %02x.%i\n", c,
reg_set->regs[c].reg,reg_set->regs[c].version,
ir_reg.reg,ir_reg.version);
-
+#endif
+
reg_set->regs[c].reg = ir_reg.reg;
reg_set->regs[c].version = ir_reg.version;
reg_set->dirty[c] = 1;
// pclog(" codegen_reg_alloc_write_reg: partial %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]);
- return reg_set->reg_list[c] | IREG_GET_SIZE(ir_reg.reg);
+ return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg);
}
/*Search for previous version in host register*/
@@ -633,8 +719,10 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg)
{
if (reg_set->regs[c].version <= ir_reg.version-1)
{
+#ifndef RELEASE_BUILD
if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount != 0)
fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n");
+#endif
break;
}
}
@@ -657,8 +745,10 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg)
if (!(reg_set->locked & (1 << c)))
break;
}
+#ifndef RELEASE_BUILD
if (c == reg_set->nr_regs)
fatal("codegen_reg_alloc_write_reg - out of registers\n");
+#endif
if (reg_set->dirty[c])
codegen_reg_writeback(reg_set, block, c, 1);
}
@@ -668,7 +758,69 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg)
reg_set->regs[c].version = ir_reg.version;
reg_set->dirty[c] = 1;
// pclog(" codegen_reg_alloc_write_reg: %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]);
- return reg_set->reg_list[c] | IREG_GET_SIZE(ir_reg.reg);
+ return reg_set->reg_list[c].reg | IREG_GET_SIZE(ir_reg.reg);
+}
+
+#ifdef CODEGEN_BACKEND_HAS_MOV_IMM
+int codegen_reg_is_loaded(ir_reg_t ir_reg)
+{
+ host_reg_set_t *reg_set = get_reg_set(ir_reg);
+ int c;
+
+ /*Search for previous version in host register*/
+ for (c = 0; c < reg_set->nr_regs; c++)
+ {
+ if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg))
+ {
+ if (reg_set->regs[c].version <= ir_reg.version-1)
+ {
+#ifndef RELEASE_BUILD
+ if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount != 0)
+ fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n");
+#endif
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+#endif
+
+void codegen_reg_rename(codeblock_t *block, ir_reg_t src, ir_reg_t dst)
+{
+ host_reg_set_t *reg_set = get_reg_set(src);
+ int c;
+ int target;
+
+// pclog("rename: %i.%i -> %i.%i\n", src.reg,src.version, dst.reg, dst.version);
+ /*Search for required register*/
+ for (c = 0; c < reg_set->nr_regs; c++)
+ {
+ if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(src.reg) && reg_set->regs[c].version == src.version)
+ break;
+ }
+#ifndef RELEASE_BUILD
+ if (c == reg_set->nr_regs)
+ fatal("codegen_reg_rename: Can't find register to rename\n");
+#endif
+ target = c;
+ if (reg_set->dirty[target])
+ codegen_reg_writeback(reg_set, block, target, 0);
+ reg_set->regs[target] = dst;
+ reg_set->dirty[target] = 1;
+// pclog("renamed reg %i dest=%i.%i\n", target, dst.reg, dst.version);
+
+ /*Invalidate any stale copies of the dest register*/
+ for (c = 0; c < reg_set->nr_regs; c++)
+ {
+ if (c == target)
+ continue;
+ if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(dst.reg))
+ {
+ reg_set->regs[c] = invalid_ir_reg;
+ reg_set->dirty[c] = 0;
+ }
+ }
}
void codegen_reg_flush(ir_data_t *ir, codeblock_t *block)
@@ -683,6 +835,11 @@ void codegen_reg_flush(ir_data_t *ir, codeblock_t *block)
{
codegen_reg_writeback(reg_set, block, c, 0);
}
+ if (reg_set->reg_list[c].flags & HOST_REG_FLAG_VOLATILE)
+ {
+ reg_set->regs[c] = invalid_ir_reg;
+ reg_set->dirty[c] = 0;
+ }
}
reg_set = &host_fp_reg_set;
@@ -692,6 +849,11 @@ void codegen_reg_flush(ir_data_t *ir, codeblock_t *block)
{
codegen_reg_writeback(reg_set, block, c, 0);
}
+ if (reg_set->reg_list[c].flags & HOST_REG_FLAG_VOLATILE)
+ {
+ reg_set->regs[c] = invalid_ir_reg;
+ reg_set->dirty[c] = 0;
+ }
}
}
diff --git a/src/codegen_reg.h b/src/codegen_reg.h
index bd790a9..4aaa231 100644
--- a/src/codegen_reg.h
+++ b/src/codegen_reg.h
@@ -325,17 +325,21 @@ static inline ir_reg_t codegen_reg_read(int reg)
ir_reg_t ireg;
reg_version_t *version;
+#ifndef RELEASE_BUILD
if (IREG_GET_REG(reg) == IREG_INVALID)
fatal("codegen_reg_read - IREG_INVALID\n");
-
+#endif
ireg.reg = reg;
ireg.version = reg_last_version[IREG_GET_REG(reg)];
version = ®_version[IREG_GET_REG(ireg.reg)][ireg.version];
version->flags = 0;
version->refcount++;
+#ifndef RELEASE_BUILD
if (!version->refcount)
fatal("codegen_reg_read - refcount overflow\n");
- else if (version->refcount > REG_REFCOUNT_MAX)
+ else
+#endif
+ if (version->refcount > REG_REFCOUNT_MAX)
CPU_BLOCK_END();
if (version->refcount > max_version_refcount)
max_version_refcount = version->refcount;
@@ -343,26 +347,35 @@ static inline ir_reg_t codegen_reg_read(int reg)
return ireg;
}
+int reg_is_native_size(ir_reg_t ir_reg);
+
static inline ir_reg_t codegen_reg_write(int reg, int uop_nr)
{
ir_reg_t ireg;
int last_version = reg_last_version[IREG_GET_REG(reg)];
reg_version_t *version;
+#ifndef RELEASE_BUILD
if (IREG_GET_REG(reg) == IREG_INVALID)
fatal("codegen_reg_write - IREG_INVALID\n");
-
+#endif
ireg.reg = reg;
ireg.version = last_version + 1;
if (IREG_GET_REG(reg) > IREG_EBX && last_version && !reg_version[IREG_GET_REG(reg)][last_version].refcount &&
!(reg_version[IREG_GET_REG(reg)][last_version].flags & REG_FLAGS_REQUIRED))
- add_to_dead_list(®_version[IREG_GET_REG(reg)][last_version], IREG_GET_REG(reg), last_version);
+ {
+ if (reg_is_native_size(ireg)) /*Non-native size registers have an implicit dependency on the previous version, so don't add to dead list*/
+ add_to_dead_list(®_version[IREG_GET_REG(reg)][last_version], IREG_GET_REG(reg), last_version);
+ }
reg_last_version[IREG_GET_REG(reg)]++;
+#ifndef RELEASE_BUILD
if (!reg_last_version[IREG_GET_REG(reg)])
fatal("codegen_reg_write - version overflow\n");
- else if (reg_last_version[IREG_GET_REG(reg)] > REG_VERSION_MAX)
+ else
+#endif
+ if (reg_last_version[IREG_GET_REG(reg)] > REG_VERSION_MAX)
CPU_BLOCK_END();
if (reg_last_version[IREG_GET_REG(reg)] > max_version_refcount)
max_version_refcount = reg_last_version[IREG_GET_REG(reg)];
@@ -391,9 +404,16 @@ void codegen_reg_flush_invalidate(struct ir_data_t *ir, codeblock_t *block);
/*Register ir_reg usage for this uOP. This ensures that required registers aren't evicted*/
void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c);
+#ifdef CODEGEN_BACKEND_HAS_MOV_IMM
+int codegen_reg_is_loaded(ir_reg_t ir_reg);
+void codegen_reg_write_imm(codeblock_t *block, ir_reg_t ir_reg, uint32_t imm_data);
+#endif
+
ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx);
ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg);
+void codegen_reg_rename(codeblock_t *block, ir_reg_t src, ir_reg_t dst);
+
void codegen_reg_mark_as_required();
void codegen_reg_process_dead_list(struct ir_data_t *ir);
#endif
diff --git a/src/codegen_timing_common.c b/src/codegen_timing_common.c
index c29f24f..a74410f 100644
--- a/src/codegen_timing_common.c
+++ b/src/codegen_timing_common.c
@@ -3,41 +3,41 @@
uint64_t opcode_deps[256] =
{
-/* ADD ADD ADD ADD*/
-/*00*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
-/* ADD ADD PUSH ES POP ES*/
- SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP,
-/* OR OR OR OR*/
- SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
-/* OR OR PUSH CS*/
- SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, 0,
+/* ADD ADD ADD ADD*/
+/*00*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
+/* ADD ADD PUSH ES POP ES*/
+ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, IMPL_ESP, IMPL_ESP,
+/* OR OR OR OR*/
+ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
+/* OR OR PUSH CS*/
+ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, IMPL_ESP, 0,
-/* ADC ADC ADC ADC*/
-/*10*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
-/* ADC ADC PUSH SS POP SS*/
- SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP,
-/* SBB SBB SBB SBB*/
- SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
-/* SBB SBB PUSH DS POP DS*/
- SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP,
+/* ADC ADC ADC ADC*/
+/*10*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
+/* ADC ADC PUSH SS POP SS*/
+ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, IMPL_ESP, IMPL_ESP,
+/* SBB SBB SBB SBB*/
+ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
+/* SBB SBB PUSH DS POP DS*/
+ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, IMPL_ESP, IMPL_ESP,
-/* AND AND AND AND*/
-/*20*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
-/* AND AND DAA*/
- SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX,
-/* SUB SUB SUB SUB*/
- SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
-/* SUB SUB DAS*/
- SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX,
+/* AND AND AND AND*/
+/*20*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
+/* AND AND DAA*/
+ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, 0, SRCDEP_EAX | DSTDEP_EAX,
+/* SUB SUB SUB SUB*/
+ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
+/* SUB SUB DAS*/
+ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, 0, SRCDEP_EAX | DSTDEP_EAX,
-/* XOR XOR XOR XOR*/
-/*30*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
-/* XOR XOR AAA*/
- SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX,
-/* CMP CMP CMP CMP*/
- SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | MODRM,
-/* CMP CMP AAS*/
- SRCDEP_EAX, SRCDEP_EAX, 0, SRCDEP_EAX | DSTDEP_EAX,
+/* XOR XOR XOR XOR*/
+/*30*/ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM, SRCDEP_REG | DSTDEP_REG | MODRM,
+/* XOR XOR AAA*/
+ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, 0, SRCDEP_EAX | DSTDEP_EAX,
+/* CMP CMP CMP CMP*/
+ SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | MODRM, SRCDEP_REG | MODRM,
+/* CMP CMP AAS*/
+ SRCDEP_EAX | HAS_IMM8, SRCDEP_EAX | HAS_IMM1632, 0, SRCDEP_EAX | DSTDEP_EAX,
/* INC EAX INC ECX INC EDX INC EBX*/
/*40*/ SRCDEP_EAX | DSTDEP_EAX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EBX | DSTDEP_EBX,
@@ -61,7 +61,7 @@ uint64_t opcode_deps[256] =
/*60*/ IMPL_ESP, IMPL_ESP, 0, 0,
0, 0, 0, 0,
/* PUSH imm IMUL PUSH imm IMUL*/
- IMPL_ESP, DSTDEP_REG | MODRM, IMPL_ESP, DSTDEP_REG | MODRM,
+ IMPL_ESP | HAS_IMM1632,DSTDEP_REG | MODRM, IMPL_ESP | HAS_IMM8, DSTDEP_REG | MODRM,
/* INSB INSW OUTSB OUTSW*/
0, 0, 0, 0,
@@ -95,15 +95,15 @@ uint64_t opcode_deps[256] =
0, 0, 0, 0,
/* MOV*/
-/*b0*/ DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX,
- DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX,
- DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX,
- DSTDEP_ESP, DSTDEP_EBP, DSTDEP_ESI, DSTDEP_EDI,
+/*b0*/ DSTDEP_EAX | HAS_IMM8, DSTDEP_ECX | HAS_IMM8, DSTDEP_EDX | HAS_IMM8, DSTDEP_EBX | HAS_IMM8,
+ DSTDEP_EAX | HAS_IMM8, DSTDEP_ECX | HAS_IMM8, DSTDEP_EDX | HAS_IMM8, DSTDEP_EBX | HAS_IMM8,
+ DSTDEP_EAX | HAS_IMM1632, DSTDEP_ECX | HAS_IMM1632, DSTDEP_EDX | HAS_IMM1632, DSTDEP_EBX | HAS_IMM1632,
+ DSTDEP_ESP | HAS_IMM1632, DSTDEP_EBP | HAS_IMM1632, DSTDEP_ESI | HAS_IMM1632, DSTDEP_EDI | HAS_IMM1632,
/* RET imm RET*/
/*c0*/ 0, 0, SRCDEP_ESP | DSTDEP_ESP, IMPL_ESP,
/* LES LDS MOV MOV*/
- DSTDEP_REG | MODRM, DSTDEP_REG | MODRM, MODRM, MODRM,
+ DSTDEP_REG | MODRM, DSTDEP_REG | MODRM, MODRM | HAS_IMM8, MODRM | HAS_IMM1632,
/* ENTER LEAVE RETF RETF*/
IMPL_ESP, IMPL_ESP, IMPL_ESP, IMPL_ESP,
/* INT3 INT INTO IRET*/
@@ -140,38 +140,38 @@ uint64_t opcode_deps_mod3[256] =
/* ADD ADD ADD ADD*/
/*00*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM,
/* ADD ADD PUSH ES POP ES*/
- SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP,
+ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, IMPL_ESP, IMPL_ESP,
/* OR OR OR OR*/
SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM,
/* OR OR PUSH CS*/
- SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, 0,
+ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, IMPL_ESP, 0,
/* ADC ADC ADC ADC*/
/*10*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM,
/* ADC ADC PUSH SS POP SS*/
- SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP,
+ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, IMPL_ESP, IMPL_ESP,
/* SBB SBB SBB SBB*/
SRCDEP_REG |SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM,
/* SBB SBB PUSH DS POP DS*/
- SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX, IMPL_ESP, IMPL_ESP,
+ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, IMPL_ESP, IMPL_ESP,
/* AND AND AND AND*/
/*20*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM,
/* AND AND DAA*/
- SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX,
+ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, 0, SRCDEP_EAX | DSTDEP_EAX,
/* SUB SUB SUB SUB*/
SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM,
/* SUB SUB DAS*/
- SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX,
+ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, 0, SRCDEP_EAX | DSTDEP_EAX,
/* XOR XOR XOR XOR*/
/*30*/ SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | DSTDEP_REG | SRCDEP_RM | MODRM,
/* XOR XOR AAA*/
- SRCDEP_EAX | DSTDEP_EAX, SRCDEP_EAX | DSTDEP_EAX | MODRM, 0, SRCDEP_EAX | DSTDEP_EAX,
+ SRCDEP_EAX | DSTDEP_EAX | HAS_IMM8, SRCDEP_EAX | DSTDEP_EAX | HAS_IMM1632, 0, SRCDEP_EAX | DSTDEP_EAX,
/* CMP CMP CMP CMP*/
SRCDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | MODRM, SRCDEP_REG | SRCDEP_RM | MODRM,
/* CMP CMP AAS*/
- SRCDEP_EAX, SRCDEP_EAX, 0, SRCDEP_EAX | DSTDEP_EAX,
+ SRCDEP_EAX | HAS_IMM8, SRCDEP_EAX | HAS_IMM1632, 0, SRCDEP_EAX | DSTDEP_EAX,
/* INC EAX INC ECX INC EDX INC EBX*/
/*40*/ SRCDEP_EAX | DSTDEP_EAX, SRCDEP_ECX | DSTDEP_ECX, SRCDEP_EDX | DSTDEP_EDX, SRCDEP_EBX | DSTDEP_EBX,
@@ -195,7 +195,7 @@ uint64_t opcode_deps_mod3[256] =
/*60*/ IMPL_ESP, IMPL_ESP, 0, 0,
0, 0, 0, 0,
/* PUSH imm IMUL PUSH imm IMUL*/
- IMPL_ESP, DSTDEP_REG | SRCDEP_RM | MODRM, IMPL_ESP, DSTDEP_REG | SRCDEP_RM | MODRM,
+ IMPL_ESP | HAS_IMM1632,DSTDEP_REG | SRCDEP_RM | MODRM, IMPL_ESP | HAS_IMM8, DSTDEP_REG | SRCDEP_RM | MODRM,
/* INSB INSW OUTSB OUTSW*/
0, 0, 0, 0,
@@ -229,19 +229,19 @@ uint64_t opcode_deps_mod3[256] =
0, 0, 0, 0,
/* MOV*/
-/*b0*/ DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX,
- DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX,
- DSTDEP_EAX, DSTDEP_ECX, DSTDEP_EDX, DSTDEP_EBX,
- DSTDEP_ESP, DSTDEP_EBP, DSTDEP_ESI, DSTDEP_EDI,
+/*b0*/ DSTDEP_EAX | HAS_IMM8, DSTDEP_ECX | HAS_IMM8, DSTDEP_EDX | HAS_IMM8, DSTDEP_EBX | HAS_IMM8,
+ DSTDEP_EAX | HAS_IMM8, DSTDEP_ECX | HAS_IMM8, DSTDEP_EDX | HAS_IMM8, DSTDEP_EBX | HAS_IMM8,
+ DSTDEP_EAX | HAS_IMM1632, DSTDEP_ECX | HAS_IMM1632, DSTDEP_EDX | HAS_IMM1632, DSTDEP_EBX | HAS_IMM1632,
+ DSTDEP_ESP | HAS_IMM1632, DSTDEP_EBP | HAS_IMM1632, DSTDEP_ESI | HAS_IMM1632, DSTDEP_EDI | HAS_IMM1632,
-/* RET imm RET*/
-/*c0*/ 0, 0, SRCDEP_ESP | DSTDEP_ESP, IMPL_ESP,
-/* LES LDS MOV MOV*/
- DSTDEP_REG | MODRM, DSTDEP_REG | MODRM, DSTDEP_RM | MODRM, DSTDEP_RM | MODRM,
-/* ENTER LEAVE RETF RETF*/
- IMPL_ESP, IMPL_ESP, IMPL_ESP, IMPL_ESP,
-/* INT3 INT INTO IRET*/
- 0, 0, 0, 0,
+/* RET imm RET*/
+/*c0*/ 0, 0, SRCDEP_ESP | DSTDEP_ESP, IMPL_ESP,
+/* LES LDS MOV MOV*/
+ DSTDEP_REG | MODRM, DSTDEP_REG | MODRM, DSTDEP_RM | MODRM | HAS_IMM8, DSTDEP_RM | MODRM | HAS_IMM1632,
+/* ENTER LEAVE RETF RETF*/
+ IMPL_ESP, IMPL_ESP, IMPL_ESP, IMPL_ESP,
+/* INT3 INT INTO IRET*/
+ 0, 0, 0, 0,
/*d0*/ 0, 0, 0, 0,
diff --git a/src/codegen_timing_cyrixiii.c b/src/codegen_timing_cyrixiii.c
new file mode 100644
index 0000000..c89defc
--- /dev/null
+++ b/src/codegen_timing_cyrixiii.c
@@ -0,0 +1,679 @@
+/*Since VIA didn't document cycle timings in the Cyrix III/C3 datasheets, and
+ I don't currently own either chip to test against, most of the timing here is
+ a guess. This code makes the current (probably wrong) assumptions, based on the
+ few details in the Cyrix III datasheet :
+ - Most common integer instructions are 1 cycle, including register-memory and
+ memory-register versions
+ - Basic FPU instructions are 2 cycles. The datasheet claims "a non-dependent
+ add or multiply can start every two clocks"; it's not clear if this is referring
+ to CPU or FPU clocks, since the FPU runs at 1/2 CPU speed on these chips.
+ - MMX instructions are 1 cycle
+ - No instruction pairing of any kind (unlike WinChip 2)
+ - Prefixes other than 0x0f cost 1 cycle each
+ - AGI stalls cost 1 cycle, except for implicit references to ESP*/
+#include "ibm.h"
+#include "cpu.h"
+#include "x86.h"
+#include "x86_ops.h"
+#include "x87.h"
+#include "mem.h"
+#include "codegen.h"
+#include "codegen_ops.h"
+#include "codegen_timing_common.h"
+
+/*Instruction has different execution time for 16 and 32 bit data. Does not pair */
+#define CYCLES_HAS_MULTI (1 << 31)
+
+#define CYCLES_FPU (1 << 30)
+
+#define CYCLES_IS_MMX_MUL (1 << 29)
+#define CYCLES_IS_MMX_SHIFT (1 << 28)
+#define CYCLES_IS_MMX_ANY (1 << 27)
+#define CYCLES_IS_3DNOW (1 << 26)
+
+#define CYCLES_MMX_MUL(c) (CYCLES_IS_MMX_MUL | c)
+#define CYCLES_MMX_SHIFT(c) (CYCLES_IS_MMX_SHIFT | c)
+#define CYCLES_MMX_ANY(c) (CYCLES_IS_MMX_ANY | c)
+#define CYCLES_3DNOW(c) (CYCLES_IS_3DNOW | c)
+
+#define CYCLES_IS_MMX (CYCLES_IS_MMX_MUL | CYCLES_IS_MMX_SHIFT | CYCLES_IS_MMX_ANY | CYCLES_IS_3DNOW)
+
+#define GET_CYCLES(c) (c & ~(CYCLES_HAS_MULTI | CYCLES_FPU | CYCLES_IS_MMX))
+
+#define CYCLES(c) c
+#define CYCLES2(c16, c32) (CYCLES_HAS_MULTI | c16 | (c32 << 8))
+
+/*comp_time = cycles until instruction complete
+ i_overlap = cycles that overlap with integer
+ f_overlap = cycles that overlap with subsequent FPU*/
+#define FPU_CYCLES(comp_time, i_overlap, f_overlap) (comp_time) | (i_overlap << 8) | (f_overlap << 16) | CYCLES_FPU
+
+#define FPU_COMP_TIME(timing) (timing & 0xff)
+#define FPU_I_OVERLAP(timing) ((timing >> 8) & 0xff)
+#define FPU_F_OVERLAP(timing) ((timing >> 16) & 0xff)
+
+#define FPU_I_LATENCY(timing) (FPU_COMP_TIME(timing) - FPU_I_OVERLAP(timing))
+
+#define FPU_F_LATENCY(timing) (FPU_I_OVERLAP(timing) - FPU_F_OVERLAP(timing))
+
+#define FPU_RESULT_LATENCY(timing) ((timing >> 8) & 0xff)
+
+#define INVALID 0
+
+static uint32_t opcode_timings[256] =
+{
+/*00*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), INVALID,
+/*10*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3),
+/*20*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3),
+/*30*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2),
+
+/*40*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
+/*50*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
+/*60*/ CYCLES(11), CYCLES(9), CYCLES(7), CYCLES(9), CYCLES(4), CYCLES(4), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES2(17,25), CYCLES(1), CYCLES2(17,20), CYCLES(17), CYCLES(17), CYCLES(17), CYCLES(17),
+/*70*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
+
+/*80*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(2), CYCLES(5), CYCLES(5), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(1), CYCLES(5), CYCLES(6),
+/*90*/ CYCLES(1), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(0), CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(2), CYCLES(3),
+/*a0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(7), CYCLES(7), CYCLES(8), CYCLES(8), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6),
+/*b0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
+
+/*c0*/ CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(1), CYCLES(1), CYCLES(14), CYCLES(5), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(3), CYCLES(0),
+/*d0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
+/*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14),
+/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), INVALID, INVALID, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), INVALID
+};
+
+static uint32_t opcode_timings_mod3[256] =
+{
+/*00*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), INVALID,
+/*10*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3),
+/*20*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3),
+/*30*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2),
+
+/*40*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
+/*50*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
+/*60*/ CYCLES(11), CYCLES(9), CYCLES(7), CYCLES(9), CYCLES(4), CYCLES(4), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES2(14,25), CYCLES(1), CYCLES2(17,20), CYCLES(17), CYCLES(17), CYCLES(17), CYCLES(17),
+/*70*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
+
+/*80*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(1), CYCLES(2), CYCLES(1),
+/*90*/ CYCLES(1), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(0), CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(2), CYCLES(3),
+/*a0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(7), CYCLES(7), CYCLES(8), CYCLES(8), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6),
+/*b0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
+
+/*c0*/ CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(1), CYCLES(1), CYCLES(14), CYCLES(5), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(3), CYCLES(0),
+/*d0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
+/*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14),
+/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), INVALID, INVALID, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), INVALID,
+};
+
+static uint32_t opcode_timings_0f[256] =
+{
+/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), INVALID, CYCLES(195), CYCLES(7), INVALID, CYCLES(1000), CYCLES(10000), INVALID, INVALID, INVALID, CYCLES_3DNOW(1), CYCLES(1), CYCLES_3DNOW(1),
+/*10*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
+/*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
+/*30*/ CYCLES(9), CYCLES(1), CYCLES(9), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
+
+/*40*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
+/*50*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
+/*60*/ CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1),
+/*70*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES(100), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1),
+
+/*80*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
+/*90*/ CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3),
+/*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), INVALID, INVALID, CYCLES(3), CYCLES(3), INVALID, CYCLES(13), CYCLES(3), CYCLES(3), INVALID, CYCLES2(18,30),
+/*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), INVALID, INVALID, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3),
+
+/*c0*/ CYCLES(4), CYCLES(4), INVALID, INVALID, INVALID, INVALID, INVALID, CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
+/*d0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1),
+/*e0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1),
+/*f0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(2), INVALID,
+};
+static uint32_t opcode_timings_0f_mod3[256] =
+{
+/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), INVALID, CYCLES(195), CYCLES(7), INVALID, CYCLES(1000), CYCLES(10000), INVALID, INVALID, INVALID, CYCLES_3DNOW(1), CYCLES(1), CYCLES_3DNOW(1),
+/*10*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
+/*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
+/*30*/ CYCLES(9), CYCLES(1), CYCLES(9), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
+
+/*40*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
+/*50*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID,
+/*60*/ CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1),
+/*70*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES(100), INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1),
+
+/*80*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
+/*90*/ CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3),
+/*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), INVALID, INVALID, CYCLES(3), CYCLES(3), INVALID, CYCLES(13), CYCLES(3), CYCLES(3), INVALID, CYCLES2(18,30),
+/*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), INVALID, INVALID, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3),
+
+/*c0*/ CYCLES(4), CYCLES(4), INVALID, INVALID, INVALID, INVALID, INVALID, CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
+/*d0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1),
+/*e0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1),
+/*f0*/ INVALID, CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), CYCLES_MMX_SHIFT(1), INVALID, CYCLES_MMX_MUL(1), INVALID, INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID, CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), CYCLES_MMX_ANY(1), INVALID,
+};
+
+static uint32_t opcode_timings_shift[8] =
+{
+ CYCLES(7), CYCLES(7), CYCLES(10), CYCLES(10), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7)
+};
+static uint32_t opcode_timings_shift_mod3[8] =
+{
+ CYCLES(3), CYCLES(3), CYCLES(9), CYCLES(9), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3)
+};
+
+static uint32_t opcode_timings_f6[8] =
+{
+ CYCLES(2), INVALID, CYCLES(2), CYCLES(2), CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19)
+};
+static uint32_t opcode_timings_f6_mod3[8] =
+{
+ CYCLES(1), INVALID, CYCLES(1), CYCLES(1), CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19)
+};
+static uint32_t opcode_timings_f7[8] =
+{
+ CYCLES(2), INVALID, CYCLES(2), CYCLES(2), CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43)
+};
+static uint32_t opcode_timings_f7_mod3[8] =
+{
+ CYCLES(1), INVALID, CYCLES(1), CYCLES(1), CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43)
+};
+static uint32_t opcode_timings_ff[8] =
+{
+ CYCLES(2), CYCLES(2), CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), INVALID
+};
+static uint32_t opcode_timings_ff_mod3[8] =
+{
+ CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), INVALID
+};
+
+static uint32_t opcode_timings_d8[8] =
+{
+/* FADDs FMULs FCOMs FCOMPs*/
+ FPU_CYCLES(4,2,2), FPU_CYCLES(4,2,2), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
+/* FSUBs FSUBRs FDIVs FDIVRs*/
+ FPU_CYCLES(4,2,2), FPU_CYCLES(4,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2)
+};
+static uint32_t opcode_timings_d8_mod3[8] =
+{
+/* FADD FMUL FCOM FCOMP*/
+ FPU_CYCLES(4,2,2), FPU_CYCLES(4,2,2), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
+/* FSUB FSUBR FDIV FDIVR*/
+ FPU_CYCLES(4,2,2), FPU_CYCLES(4,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2)
+};
+
+static uint32_t opcode_timings_d9[8] =
+{
+/* FLDs FSTs FSTPs*/
+ FPU_CYCLES(2,0,0), INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
+/* FLDENV FLDCW FSTENV FSTCW*/
+ FPU_CYCLES(32,0,0), FPU_CYCLES(8,0,0), FPU_CYCLES(48,0,0), FPU_CYCLES(2,0,0)
+};
+static uint32_t opcode_timings_d9_mod3[64] =
+{
+ /*FLD*/
+ FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
+ FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
+ /*FXCH*/
+ FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
+ FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
+ /*FNOP*/
+ FPU_CYCLES(3,0,0), INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ /*FSTP*/
+ FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
+ FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
+/* opFCHS opFABS*/
+ FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), INVALID, INVALID,
+/* opFTST opFXAM*/
+ FPU_CYCLES(2,0,0), FPU_CYCLES(21,4,0), INVALID, INVALID,
+/* opFLD1 opFLDL2T opFLDL2E opFLDPI*/
+ FPU_CYCLES(2,0,0), FPU_CYCLES(5,2,2), FPU_CYCLES(5,2,2), FPU_CYCLES(5,2,2),
+/* opFLDEG2 opFLDLN2 opFLDZ*/
+ FPU_CYCLES(5,2,2), FPU_CYCLES(5,2,2), FPU_CYCLES(2,0,0), INVALID,
+/* opF2XM1 opFYL2X opFPTAN opFPATAN*/
+ FPU_CYCLES(53,2,2), FPU_CYCLES(103,2,2),FPU_CYCLES(120,36,0),FPU_CYCLES(112,2,2),
+/* opFDECSTP opFINCSTP,*/
+ INVALID, INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
+/* opFPREM opFSQRT opFSINCOS*/
+ FPU_CYCLES(64,2,2), INVALID, FPU_CYCLES(70,69,2),FPU_CYCLES(89,2,2),
+/* opFRNDINT opFSCALE opFSIN opFCOS*/
+ FPU_CYCLES(9,0,0), FPU_CYCLES(20,5,0), FPU_CYCLES(65,2,2), FPU_CYCLES(65,2,2)
+};
+
+static uint32_t opcode_timings_da[8] =
+{
+/* FIADDl FIMULl FICOMl FICOMPl*/
+ FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(4,0,0), FPU_CYCLES(4,0,0),
+/* FISUBl FISUBRl FIDIVl FIDIVRl*/
+ FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(42,38,2), FPU_CYCLES(42,38,2)
+};
+static uint32_t opcode_timings_da_mod3[8] =
+{
+ INVALID, INVALID, INVALID, INVALID,
+/* FCOMPP*/
+ INVALID, FPU_CYCLES(2,0,0), INVALID, INVALID
+};
+
+
+static uint32_t opcode_timings_db[8] =
+{
+/* FLDil FSTil FSTPil*/
+ FPU_CYCLES(3,2,2), INVALID, FPU_CYCLES(6,0,0), FPU_CYCLES(6,0,0),
+/* FLDe FSTPe*/
+ INVALID, FPU_CYCLES(3,0,0), INVALID, FPU_CYCLES(3,0,0)
+};
+static uint32_t opcode_timings_db_mod3[64] =
+{
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+/* opFNOP opFCLEX opFINIT*/
+ INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(7,0,0), FPU_CYCLES(17,0,0),
+/* opFNOP opFNOP*/
+ FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), INVALID, INVALID,
+
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+};
+
+static uint32_t opcode_timings_dc[8] =
+{
+/* FADDd FMULd FCOMd FCOMPd*/
+ FPU_CYCLES(4,2,2), FPU_CYCLES(4,2,2), FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
+/* FSUBd FSUBRd FDIVd FDIVRd*/
+ FPU_CYCLES(4,2,2), FPU_CYCLES(4,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2)
+};
+static uint32_t opcode_timings_dc_mod3[8] =
+{
+/* opFADDr opFMULr*/
+ FPU_CYCLES(4,2,2), FPU_CYCLES(4,2,2),INVALID, INVALID,
+/* opFSUBRr opFSUBr opFDIVRr opFDIVr*/
+ FPU_CYCLES(4,2,2), FPU_CYCLES(4,2,2),FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2)
+};
+
+static uint32_t opcode_timings_dd[8] =
+{
+/* FLDd FSTd FSTPd*/
+ FPU_CYCLES(2,0,0), INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
+/* FRSTOR FSAVE FSTSW*/
+ FPU_CYCLES(70,0,0), INVALID, FPU_CYCLES(127,0,0), FPU_CYCLES(6,0,0)
+};
+static uint32_t opcode_timings_dd_mod3[8] =
+{
+/* FFFREE FST FSTP*/
+ FPU_CYCLES(2,0,0), INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),
+/* FUCOM FUCOMP*/
+ FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0),INVALID, INVALID
+};
+
+static uint32_t opcode_timings_de[8] =
+{
+/* FIADDw FIMULw FICOMw FICOMPw*/
+ FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(4,0,0), FPU_CYCLES(4,0,0),
+/* FISUBw FISUBRw FIDIVw FIDIVRw*/
+ FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(42,38,2), FPU_CYCLES(42,38,2)
+};
+static uint32_t opcode_timings_de_mod3[8] =
+{
+/* FADDP FMULP FCOMPP*/
+ FPU_CYCLES(4,2,2), FPU_CYCLES(4,2,2), INVALID, FPU_CYCLES(2,0,0),
+/* FSUBP FSUBRP FDIVP FDIVRP*/
+ FPU_CYCLES(4,2,2), FPU_CYCLES(4,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2)
+};
+
+static uint32_t opcode_timings_df[8] =
+{
+/* FILDiw FISTiw FISTPiw*/
+ FPU_CYCLES(3,2,2), INVALID, FPU_CYCLES(6,0,0), FPU_CYCLES(6,0,0),
+/* FILDiq FBSTP FISTPiq*/
+ INVALID, FPU_CYCLES(3,2,2), FPU_CYCLES(148,0,0), FPU_CYCLES(6,0,0)
+};
+static uint32_t opcode_timings_df_mod3[8] =
+{
+ INVALID, INVALID, INVALID, INVALID,
+/* FSTSW AX*/
+ FPU_CYCLES(6,0,0), INVALID, INVALID, INVALID
+};
+
+static uint32_t opcode_timings_8x[8] =
+{
+ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2)
+};
+static uint32_t opcode_timings_8x_mod3[8] =
+{
+ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2)
+};
+static uint32_t opcode_timings_81[8] =
+{
+ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2)
+};
+static uint32_t opcode_timings_81_mod3[8] =
+{
+ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2)
+};
+
+static int timing_count;
+static uint8_t last_prefix;
+static uint32_t regmask_modified;
+static int decode_delay, decode_delay_offset;
+static int fpu_latency;
+static int fpu_st_latency[8];
+
+
+static inline int COUNT(uint32_t c, int op_32)
+{
+ if (c & CYCLES_FPU)
+ return FPU_I_LATENCY(c);
+ if (c & CYCLES_HAS_MULTI)
+ {
+ if (op_32 & 0x100)
+ return (c >> 8) & 0xff;
+ return c & 0xff;
+ }
+ return GET_CYCLES(c);
+}
+
+static int check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_32)
+{
+ uint32_t addr_regmask = get_addr_regmask(deps[opcode], fetchdat, op_32);
+
+ /*Instructions that use ESP implicitly (eg PUSH, POP, CALL etc) do not
+ cause AGIs with each other, but do with instructions that use it explicitly*/
+ if ((addr_regmask & REGMASK_IMPL_ESP) && (regmask_modified & (1 << REG_ESP)) && !(regmask_modified & REGMASK_IMPL_ESP))
+ addr_regmask |= (1 << REG_ESP);
+
+ return (regmask_modified & addr_regmask) & ~REGMASK_IMPL_ESP;
+}
+
+static int codegen_fpu_latencies(uint64_t deps, int reg)
+{
+ int latency = fpu_latency;
+
+ if ((deps & FPU_RW_ST0) && fpu_st_latency[0] && fpu_st_latency[0] > latency)
+ latency = fpu_st_latency[0];
+ if ((deps & FPU_RW_ST1) && fpu_st_latency[1] && fpu_st_latency[1] > latency)
+ latency = fpu_st_latency[1];
+ if ((deps & FPU_RW_STREG) && fpu_st_latency[reg] && fpu_st_latency[reg] > latency)
+ latency = fpu_st_latency[reg];
+
+ return latency;
+}
+
+#define SUB_AND_CLAMP(latency, count) \
+ latency -= count; \
+ if (latency < 0) \
+ latency = 0
+
+static void codegen_fpu_latency_clock(int count)
+{
+ SUB_AND_CLAMP(fpu_latency, count);
+ SUB_AND_CLAMP(fpu_st_latency[0], count);
+ SUB_AND_CLAMP(fpu_st_latency[1], count);
+ SUB_AND_CLAMP(fpu_st_latency[2], count);
+ SUB_AND_CLAMP(fpu_st_latency[3], count);
+ SUB_AND_CLAMP(fpu_st_latency[4], count);
+ SUB_AND_CLAMP(fpu_st_latency[5], count);
+ SUB_AND_CLAMP(fpu_st_latency[6], count);
+ SUB_AND_CLAMP(fpu_st_latency[7], count);
+}
+
+static void codegen_instruction(uint32_t *timings, uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int decode_delay_offset, int op_32, int exec_delay)
+{
+ int instr_cycles, latency = 0;
+
+ if ((timings[opcode] & CYCLES_FPU) && !(deps[opcode] & FPU_FXCH))
+ instr_cycles = latency = codegen_fpu_latencies(deps[opcode], fetchdat & 7);
+ else
+ instr_cycles = 0;
+
+ if ((decode_delay + decode_delay_offset) > 0)
+ codegen_fpu_latency_clock(decode_delay + decode_delay_offset + instr_cycles);
+ else
+ codegen_fpu_latency_clock(instr_cycles);
+ instr_cycles += COUNT(timings[opcode], op_32);
+ instr_cycles += exec_delay;
+ if ((decode_delay + decode_delay_offset) > 0)
+ codegen_block_cycles += instr_cycles + decode_delay + decode_delay_offset;
+ else
+ codegen_block_cycles += instr_cycles;
+ decode_delay = (-instr_cycles) + 1;
+
+ if (deps[opcode] & FPU_POP)
+ {
+ int c;
+
+ for (c = 0; c < 7; c++)
+ fpu_st_latency[c] = fpu_st_latency[c+1];
+ fpu_st_latency[7] = 0;
+ }
+ if (deps[opcode] & FPU_POP2)
+ {
+ int c;
+
+ for (c = 0; c < 6; c++)
+ fpu_st_latency[c] = fpu_st_latency[c+2];
+ fpu_st_latency[6] = fpu_st_latency[7] = 0;
+ }
+ if (timings[opcode] & CYCLES_FPU)
+ {
+ /* if (fpu_latency)
+ fatal("Bad latency FPU\n");*/
+ fpu_latency = FPU_F_LATENCY(timings[opcode]);
+ }
+
+ if (deps[opcode] & FPU_PUSH)
+ {
+ int c;
+
+ for (c = 0; c < 7; c++)
+ fpu_st_latency[c+1] = fpu_st_latency[c];
+ fpu_st_latency[0] = 0;
+ }
+ if (deps[opcode] & FPU_WRITE_ST0)
+ {
+/* if (fpu_st_latency[0])
+ fatal("Bad latency ST0\n");*/
+ fpu_st_latency[0] = FPU_RESULT_LATENCY(timings[opcode]);
+ }
+ if (deps[opcode] & FPU_WRITE_ST1)
+ {
+/* if (fpu_st_latency[1])
+ fatal("Bad latency ST1\n");*/
+ fpu_st_latency[1] = FPU_RESULT_LATENCY(timings[opcode]);
+ }
+ if (deps[opcode] & FPU_WRITE_STREG)
+ {
+ int reg = fetchdat & 7;
+ if (deps[opcode] & FPU_POP)
+ reg--;
+ if (reg >= 0 &&
+ !(reg == 0 && (deps[opcode] & FPU_WRITE_ST0)) &&
+ !(reg == 1 && (deps[opcode] & FPU_WRITE_ST1)))
+ {
+/* if (fpu_st_latency[reg])
+ fatal("Bad latency STREG %i %08x %i %016llx %02x\n",fpu_st_latency[reg], fetchdat, reg, timings[opcode], opcode);*/
+ fpu_st_latency[reg] = FPU_RESULT_LATENCY(timings[opcode]);
+ }
+ }
+}
+
+static void codegen_timing_cyrixiii_block_start()
+{
+ regmask_modified = 0;
+ decode_delay = decode_delay_offset = 0;
+}
+
+static void codegen_timing_cyrixiii_start()
+{
+ timing_count = 0;
+ last_prefix = 0;
+}
+
+static void codegen_timing_cyrixiii_prefix(uint8_t prefix, uint32_t fetchdat)
+{
+ if (prefix == 0x0f)
+ {
+ /*0fh prefix is 'free'*/
+ last_prefix = prefix;
+ return;
+ }
+ /*On C3 all prefixes take 1 cycle to decode. Decode may be shadowed
+ by execution of previous instructions*/
+ decode_delay_offset++;
+ last_prefix = prefix;
+}
+
+static void codegen_timing_cyrixiii_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc)
+{
+ uint32_t *timings;
+ uint64_t *deps;
+ int mod3 = ((fetchdat & 0xc0) == 0xc0);
+ int bit8 = !(opcode & 1);
+ int agi_stall = 0;
+
+ switch (last_prefix)
+ {
+ case 0x0f:
+ timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f;
+ deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f;
+// pclog("timings 0f\n");
+ break;
+
+ case 0xd8:
+ timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8;
+ deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8;
+ opcode = (opcode >> 3) & 7;
+// pclog("timings d8\n");
+ break;
+ case 0xd9:
+ timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9;
+ deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9;
+ opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7;
+// pclog("timings d9\n");
+ break;
+ case 0xda:
+ timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da;
+ deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da;
+ opcode = (opcode >> 3) & 7;
+// pclog("timings da\n");
+ break;
+ case 0xdb:
+ timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db;
+ deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db;
+ opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7;
+// pclog("timings db\n");
+ break;
+ case 0xdc:
+ timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc;
+ deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc;
+ opcode = (opcode >> 3) & 7;
+// pclog("timings dc\n");
+ break;
+ case 0xdd:
+ timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd;
+ deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd;
+ opcode = (opcode >> 3) & 7;
+// pclog("timings dd\n");
+ break;
+ case 0xde:
+ timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de;
+ deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de;
+ opcode = (opcode >> 3) & 7;
+// pclog("timings de\n");
+ break;
+ case 0xdf:
+ timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df;
+ deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df;
+ opcode = (opcode >> 3) & 7;
+// pclog("timings df\n");
+ break;
+
+ default:
+ switch (opcode)
+ {
+ case 0x80: case 0x82: case 0x83:
+ timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x;
+ deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3;
+ opcode = (fetchdat >> 3) & 7;
+// pclog("timings 80 %p %p %p\n", (void *)timings, (void *)opcode_timings_mod3, (void *)opcode_timings_8x);
+ break;
+ case 0x81:
+ timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81;
+ deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81;
+ opcode = (fetchdat >> 3) & 7;
+// pclog("timings 80 %p %p %p\n", (void *)timings, (void *)opcode_timings_mod3, (void *)opcode_timings_8x);
+ break;
+
+ case 0xc0: case 0xc1: case 0xd0: case 0xd1: case 0xd2: case 0xd3:
+ timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift;
+ deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift;
+ opcode = (fetchdat >> 3) & 7;
+// pclog("timings c0\n");
+ break;
+
+ case 0xf6:
+ timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6;
+ deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6;
+ opcode = (fetchdat >> 3) & 7;
+// pclog("timings f6\n");
+ break;
+ case 0xf7:
+ timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7;
+ deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7;
+ opcode = (fetchdat >> 3) & 7;
+// pclog("timings f7\n");
+ break;
+ case 0xff:
+ timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff;
+ deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff;
+ opcode = (fetchdat >> 3) & 7;
+// pclog("timings ff\n");
+ break;
+
+ default:
+ timings = mod3 ? opcode_timings_mod3 : opcode_timings;
+ deps = mod3 ? opcode_deps_mod3 : opcode_deps;
+// pclog("timings normal\n");
+ break;
+ }
+ }
+
+ if (check_agi(deps, opcode, fetchdat, op_32))
+ agi_stall = 1;
+ codegen_instruction(timings, deps, opcode, fetchdat, decode_delay_offset, op_32, agi_stall);
+ decode_delay_offset = 0;
+ regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8);
+}
+
+static void codegen_timing_cyrixiii_block_end()
+{
+}
+
+int codegen_timing_cyrixiii_jump_cycles()
+{
+ return 0;
+}
+
+codegen_timing_t codegen_timing_cyrixiii =
+{
+ codegen_timing_cyrixiii_start,
+ codegen_timing_cyrixiii_prefix,
+ codegen_timing_cyrixiii_opcode,
+ codegen_timing_cyrixiii_block_start,
+ codegen_timing_cyrixiii_block_end,
+ codegen_timing_cyrixiii_jump_cycles
+};
diff --git a/src/codegen_timing_p6.c b/src/codegen_timing_p6.c
new file mode 100644
index 0000000..a608164
--- /dev/null
+++ b/src/codegen_timing_p6.c
@@ -0,0 +1,2154 @@
+#include "ibm.h"
+#include "cpu.h"
+#include "model.h"
+#include "x86.h"
+#include "x86_ops.h"
+#include "x87.h"
+#include "386_common.h"
+#include "mem.h"
+#include "codegen.h"
+#include "codegen_ops.h"
+#include "codegen_timing_common.h"
+
+typedef enum uop_type_t
+{
+ UOP_ALU0 = 0, /*Executes in port 0 ALU*/
+ UOP_ALU1, /*Executes in port 1 ALU*/
+ UOP_ALU01, /*Executes in either port 0 or 1 ALU*/
+ UOP_BRANCH, /*Executes in port 1 branch*/
+ UOP_LOAD, /*Executes in port 2 Load unit*/
+ UOP_STOREADDR, /*Executes in port 3 Store Address unit*/
+ UOP_STOREDATA, /*Executes in port 4 Store Data unit*/
+ UOP_FLOAT, /*Executes in port 0 Floating Point unit*/
+ UOP_ALU0_SEG /*Executes in port 0 ALU, loads segment, causing pipeline flush on PPro*/
+} uop_type_t;
+
+#define MAX_UOPS 300
+
+typedef struct p6_uop_t
+{
+ uop_type_t type;
+ int throughput;
+ int latency;
+} p6_uop_t;
+
+typedef struct p6_instruction_t
+{
+ int nr_uops;
+ p6_uop_t uop[MAX_UOPS];
+} p6_instruction_t;
+
+static const p6_instruction_t alu_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t alu0_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t alu1_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_ALU1, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t alu01_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t alu4_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t alu6_op =
+{
+ .nr_uops = 6,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t aluc_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t load_alu_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t load_aluc_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t alu_store_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t alu0_store_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t aluc_store_op =
+{
+ .nr_uops = 6,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}
+};
+
+static const p6_instruction_t branch_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1}
+};
+
+static const p6_instruction_t load_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}
+};
+
+static const p6_instruction_t store_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}
+};
+
+
+static const p6_instruction_t bswap_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t leave_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t lods_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t loop_op =
+{
+ .nr_uops = 11,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU1, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[7] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[8] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[9] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[10] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+};
+static const p6_instruction_t movs_op =
+{
+ .nr_uops = 6,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+};
+static const p6_instruction_t pop_reg_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t pop_mem_op =
+{
+ .nr_uops = 8,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[7] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t push_imm_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t push_mem_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+};
+static const p6_instruction_t push_seg_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t rcx_op =
+{
+ .nr_uops = 8,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[7] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+};
+static const p6_instruction_t rcx_store_op =
+{
+ .nr_uops = 11,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[7] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[8] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[9] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[10] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t stos_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t xchg_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+
+static const p6_instruction_t mmx_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t mmx_mul_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 3}
+};
+static const p6_instruction_t mmx_shift_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_ALU1, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t load_mmx_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t load_mmx_mul_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t load_mmx_shift_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU1, .throughput = 1, .latency = 1}
+};
+
+static const p6_instruction_t faddsub_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 3}
+};
+static const p6_instruction_t load_faddsub_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_FLOAT, .throughput = 1, .latency = 3}
+};
+static const p6_instruction_t fbstp_op =
+{
+ .nr_uops = 5,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 165, .latency = 165},
+ .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t fcom_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t load_fcom_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t fcompp_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t fild_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t load_fi_op =
+{
+ .nr_uops = 7,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t fmul_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 5}
+};
+static const p6_instruction_t load_fmul_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_FLOAT, .throughput = 1, .latency = 5}
+};
+
+static const p6_instruction_t fxch_op =
+{
+ .nr_uops = 0
+};
+
+static const p6_instruction_t fist_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}
+};
+
+static const p6_instruction_t fdiv_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 37, .latency = 38}
+};
+static const p6_instruction_t fdiv_mem_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_FLOAT, .throughput = 37, .latency = 38}
+};
+static const p6_instruction_t fsin_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 62, .latency = 62}
+};
+static const p6_instruction_t fsqrt_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 69, .latency = 69}
+};
+
+static const p6_instruction_t float_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}
+};
+
+static const p6_instruction_t fldcw_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_FLOAT, .throughput = 7, .latency = 7},
+};
+static const p6_instruction_t flde_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[2] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t frstor_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 72, .latency = 72}
+};
+static const p6_instruction_t fsave_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 141, .latency = 141}
+};
+static const p6_instruction_t fste_op =
+{
+ .nr_uops = 6,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t fstsw_ax_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t fstsw_mem_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_FLOAT, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}
+};
+
+static const p6_instruction_t aad_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 4},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t aam_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 4},
+ .uop[2] = {.type = UOP_ALU1, .throughput = 1, .latency = 9},
+ .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t arpl_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 3, .latency = 3},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 3, .latency = 3}
+};
+static const p6_instruction_t bound_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[2] = {.type = UOP_ALU0, .throughput = 7, .latency = 7},
+ .uop[3] = {.type = UOP_ALU01, .throughput = 6, .latency = 6}
+};
+static const p6_instruction_t bsx_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU1, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t load_bsx_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU1, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t call_far_op =
+{
+ .nr_uops = 6,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_ALU0_SEG, .throughput = 28, .latency = 28}
+};
+static const p6_instruction_t load_call_far_op =
+{
+ .nr_uops = 7,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_ALU0_SEG, .throughput = 28, .latency = 28}
+};
+static const p6_instruction_t cli_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 9, .latency = 9}
+};
+static const p6_instruction_t sti_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 17, .latency = 17}
+};
+static const p6_instruction_t cmps_op =
+{
+ .nr_uops = 6,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t cmpxchg_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t cpuid_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 48, .latency = 48}
+};
+/*static const p6_instruction_t div8_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 12, .latency = 17},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};*/
+/*static const p6_instruction_t div8_mem_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[0] = {.type = UOP_ALU0, .throughput = 12, .latency = 17},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};*/
+static const p6_instruction_t div16_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 21, .latency = 21},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t div16_mem_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[0] = {.type = UOP_ALU0, .throughput = 21, .latency = 21},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t div32_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 35, .latency = 35},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t div32_mem_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[0] = {.type = UOP_ALU0, .throughput = 35, .latency = 35},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t emms_op =
+{
+ .nr_uops = 11,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[7] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[8] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[9] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[10] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t enter_op =
+{
+ .nr_uops = 14,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[7] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[8] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[9] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[10] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[11] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[12] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[13] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t io_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 18, .latency = 18}
+};
+static const p6_instruction_t ins_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 18, .latency = 18},
+ .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t int_op =
+{
+ .nr_uops = 7,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 20, .latency = 20},
+ .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+};
+static const p6_instruction_t iret_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[3] = {.type = UOP_ALU01, .throughput = 20, .latency = 20},
+};
+static const p6_instruction_t invd_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1000, .latency = 1000}
+};
+static const p6_instruction_t jmp_far_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU0_SEG, .throughput = 21, .latency = 21}
+};
+static const p6_instruction_t load_jmp_far_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[2] = {.type = UOP_ALU0_SEG, .throughput = 21, .latency = 21}
+};
+static const p6_instruction_t lss_op =
+{
+ .nr_uops = 11,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[3] = {.type = UOP_ALU0_SEG,.throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[7] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[8] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[9] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[10] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+/*static const p6_instruction_t mov_mem_seg_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+};*/
+static const p6_instruction_t mov_seg_mem_op =
+{
+ .nr_uops = 9,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU0_SEG,.throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[7] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[8] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t mov_seg_reg_op =
+{
+ .nr_uops = 8,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU0_SEG,.throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[7] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t mul_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 4}
+};
+static const p6_instruction_t mul_mem_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 4}
+};
+static const p6_instruction_t outs_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 18, .latency = 18},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t pusha_op =
+{
+ .nr_uops = 18,
+ .uop[0] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[7] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[8] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[9] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[10] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[11] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[12] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[13] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[14] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[15] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[16] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[17] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t popa_op =
+{
+ .nr_uops = 10,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_LOAD, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_LOAD, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_LOAD, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_LOAD, .throughput = 1, .latency = 1},
+ .uop[7] = {.type = UOP_LOAD, .throughput = 1, .latency = 1},
+ .uop[8] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[9] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t popf_op =
+{
+ .nr_uops = 17,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[7] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[8] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[9] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[10] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[11] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[12] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[13] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[14] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[15] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[16] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+};
+static const p6_instruction_t pushf_op =
+{
+ .nr_uops = 16,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[7] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[8] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[9] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[10] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[11] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[12] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[13] = {.type = UOP_ALU0, .throughput = 1, .latency = 1},
+ .uop[14] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[15] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t ret_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU1, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t reti_op =
+{
+ .nr_uops = 5,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_ALU1, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t retf_op =
+{
+ .nr_uops = 4,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[3] = {.type = UOP_ALU0, .throughput = 23, .latency = 23},
+};
+static const p6_instruction_t scas_op =
+{
+ .nr_uops = 3,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t xchg_mem_op =
+{
+ .nr_uops = 7,
+ .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[2] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[4] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1},
+ .uop[5] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1},
+ .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}
+};
+static const p6_instruction_t xlat_op =
+{
+ .nr_uops = 2,
+ .uop[0] = {.type = UOP_ALU01, .throughput = 1, .latency = 1},
+ .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}
+};
+static const p6_instruction_t wbinvd_op =
+{
+ .nr_uops = 1,
+ .uop[0] = {.type = UOP_ALU0, .throughput = 10000, .latency = 10000}
+};
+
+#define INVALID NULL
+
+static const p6_instruction_t *opcode_timings[256] =
+{
+/* ADD ADD ADD ADD*/
+/*00*/ &alu_store_op, &alu_store_op, &load_alu_op, &load_alu_op,
+/* ADD ADD PUSH ES POP ES*/
+ &alu_op, &alu_op, &push_seg_op, &mov_seg_mem_op,
+/* OR OR OR OR*/
+ &alu_store_op, &alu_store_op, &load_alu_op, &load_alu_op,
+/* OR OR PUSH CS */
+ &alu_op, &alu_op, &push_seg_op, INVALID,
+
+/* ADC ADC ADC ADC*/
+/*10*/ &aluc_store_op, &aluc_store_op, &load_aluc_op, &load_aluc_op,
+/* ADC ADC PUSH SS POP SS*/
+ &aluc_op, &aluc_op, &push_seg_op, &mov_seg_mem_op,
+/* SBB SBB SBB SBB*/
+/*10*/ &aluc_store_op, &aluc_store_op, &load_aluc_op, &load_aluc_op,
+/* SBB SBB PUSH DS POP DS*/
+ &aluc_op, &aluc_op, &push_seg_op, &mov_seg_mem_op,
+
+/* AND AND AND AND*/
+/*20*/ &alu_store_op, &alu_store_op, &load_alu_op, &load_alu_op,
+/* AND AND DAA*/
+ &alu_op, &alu_op, INVALID, &alu1_op,
+/* SUB SUB SUB SUB*/
+ &alu_store_op, &alu_store_op, &load_alu_op, &load_alu_op,
+/* SUB SUB DAS*/
+ &alu_op, &alu_op, INVALID, &alu1_op,
+
+/* XOR XOR XOR XOR*/
+/*30*/ &alu_store_op, &alu_store_op, &load_alu_op, &load_alu_op,
+/* XOR XOR AAA*/
+ &alu_op, &alu_op, INVALID, &alu1_op,
+/* CMP CMP CMP CMP*/
+ &load_alu_op, &load_alu_op, &load_alu_op, &load_alu_op,
+/* CMP CMP AAS*/
+ &alu_op, &alu_op, INVALID, &alu1_op,
+
+/* INC EAX INC ECX INC EDX INC EBX*/
+/*40*/ &alu_op, &alu_op, &alu_op, &alu_op,
+/* INC ESP INC EBP INC ESI INC EDI*/
+ &alu_op, &alu_op, &alu_op, &alu_op,
+/* DEC EAX DEC ECX DEC EDX DEC EBX*/
+ &alu_op, &alu_op, &alu_op, &alu_op,
+/* DEC ESP DEC EBP DEC ESI DEC EDI*/
+ &alu_op, &alu_op, &alu_op, &alu_op,
+
+/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/
+/*50*/ &store_op, &store_op, &store_op, &store_op,
+/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/
+ &store_op, &store_op, &store_op, &store_op,
+/* POP EAX POP ECX POP EDX POP EBX*/
+ &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op,
+/* POP ESP POP EBP POP ESI POP EDI*/
+ &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op,
+
+/* PUSHA POPA BOUND ARPL*/
+/*60*/ &pusha_op, &popa_op, &bound_op, &arpl_op,
+ INVALID, INVALID, INVALID, INVALID,
+/* PUSH imm IMUL PUSH imm IMUL*/
+ &push_imm_op, &mul_op, &push_imm_op, &mul_op,
+/* INSB INSW OUTSB OUTSW*/
+ &ins_op, &ins_op, &outs_op, &outs_op,
+
+/* Jxx*/
+/*70*/ &branch_op, &branch_op, &branch_op, &branch_op,
+ &branch_op, &branch_op, &branch_op, &branch_op,
+ &branch_op, &branch_op, &branch_op, &branch_op,
+ &branch_op, &branch_op, &branch_op, &branch_op,
+
+/*80*/ INVALID, INVALID, INVALID, INVALID,
+/* TEST TEST XCHG XCHG*/
+ &load_alu_op, &load_alu_op, &xchg_mem_op, &xchg_mem_op,
+/* MOV MOV MOV MOV*/
+ &store_op, &store_op, &load_op, &load_op,
+/* MOV from seg LEA MOV to seg POP*/
+ &store_op, &alu0_op, &mov_seg_mem_op, &pop_mem_op,
+
+/* NOP XCHG XCHG XCHG*/
+/*90*/ &alu_op, &xchg_op, &xchg_op, &xchg_op,
+/* XCHG XCHG XCHG XCHG*/
+ &xchg_op, &xchg_op, &xchg_op, &xchg_op,
+/* CBW CWD CALL far WAIT*/
+ &alu_op, &alu0_op, &call_far_op, &alu_op,
+/* PUSHF POPF SAHF LAHF*/
+ &pushf_op, &popf_op, &alu_op, &alu_op,
+
+/* MOV MOV MOV MOV*/
+/*a0*/ &load_op, &load_op, &store_op, &store_op,
+/* MOVSB MOVSW CMPSB CMPSW*/
+ &movs_op, &movs_op, &cmps_op, &cmps_op,
+/* TEST TEST STOSB STOSW*/
+ &load_alu_op, &load_alu_op, &stos_op, &stos_op,
+/* LODSB LODSW SCASB SCASW*/
+ &lods_op, &lods_op, &scas_op, &scas_op,
+
+/* MOV*/
+/*b0*/ &alu_op, &alu_op, &alu_op, &alu_op,
+ &alu_op, &alu_op, &alu_op, &alu_op,
+ &alu_op, &alu_op, &alu_op, &alu_op,
+ &alu_op, &alu_op, &alu_op, &alu_op,
+
+/* RET imm RET*/
+/*c0*/ INVALID, INVALID, &reti_op, &ret_op,
+/* LES LDS MOV MOV*/
+ &lss_op, &lss_op, &store_op, &store_op,
+/* ENTER LEAVE RETF RETF*/
+ &enter_op, &leave_op, &retf_op, &retf_op,
+/* INT3 INT INTO IRET*/
+ &int_op, &int_op, &int_op, &iret_op,
+
+
+/*d0*/ INVALID, INVALID, INVALID, INVALID,
+/* AAM AAD SETALC XLAT*/
+ &aam_op, &aad_op, &alu_op, &xlat_op,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+/* LOOPNE LOOPE LOOP JCXZ*/
+/*e0*/ &loop_op, &loop_op, &loop_op, &loop_op,
+/* IN AL IN AX OUT_AL OUT_AX*/
+ &io_op, &io_op, &io_op, &io_op,
+/* CALL JMP JMP JMP*/
+ &store_op, &branch_op, &jmp_far_op, &branch_op,
+/* IN AL IN AX OUT_AL OUT_AX*/
+ &io_op, &io_op, &io_op, &io_op,
+
+/* REPNE REPE*/
+/*f0*/ INVALID, INVALID, INVALID, INVALID,
+/* HLT CMC*/
+ &alu4_op, &alu_op, INVALID, INVALID,
+/* CLC STC CLI STI*/
+ &alu_op, &alu_op, &cli_op, &sti_op,
+/* CLD STD INCDEC*/
+ &alu4_op, &alu4_op, &store_op, INVALID
+};
+
+static const p6_instruction_t *opcode_timings_mod3[256] =
+{
+/* ADD ADD ADD ADD*/
+/*00*/ &alu_op, &alu_op, &alu_op, &alu_op,
+/* ADD ADD PUSH ES POP ES*/
+ &alu_op, &alu_op, &push_seg_op, &mov_seg_mem_op,
+/* OR OR OR OR*/
+ &alu_op, &alu_op, &alu_op, &alu_op,
+/* OR OR PUSH CS */
+ &alu_op, &alu_op, &push_seg_op, INVALID,
+
+/* ADC ADC ADC ADC*/
+/*10*/ &aluc_op, &aluc_op, &aluc_op, &aluc_op,
+/* ADC ADC PUSH SS POP SS*/
+ &aluc_op, &aluc_op, &push_seg_op, &mov_seg_mem_op,
+/* SBB SBB SBB SBB*/
+ &aluc_op, &aluc_op, &aluc_op, &aluc_op,
+/* SBB SBB PUSH DS POP DS*/
+ &aluc_op, &aluc_op, &push_seg_op, &mov_seg_mem_op,
+
+/* AND AND AND AND*/
+/*20*/ &alu_op, &alu_op, &alu_op, &alu_op,
+/* AND AND DAA*/
+ &alu_op, &alu_op, INVALID, &alu1_op,
+/* SUB SUB SUB SUB*/
+ &alu_op, &alu_op, &alu_op, &alu_op,
+/* SUB SUB DAS*/
+ &alu_op, &alu_op, INVALID, &alu1_op,
+
+/* XOR XOR XOR XOR*/
+/*30*/ &alu_op, &alu_op, &alu_op, &alu_op,
+/* XOR XOR AAA*/
+ &alu_op, &alu_op, INVALID, &alu1_op,
+/* CMP CMP CMP CMP*/
+ &alu_op, &alu_op, &alu_op, &alu_op,
+/* CMP CMP AAS*/
+ &alu_op, &alu_op, INVALID, &alu1_op,
+
+/* INC EAX INC ECX INC EDX INC EBX*/
+/*40*/ &alu_op, &alu_op, &alu_op, &alu_op,
+/* INC ESP INC EBP INC ESI INC EDI*/
+ &alu_op, &alu_op, &alu_op, &alu_op,
+/* DEC EAX DEC ECX DEC EDX DEC EBX*/
+ &alu_op, &alu_op, &alu_op, &alu_op,
+/* DEC ESP DEC EBP DEC ESI DEC EDI*/
+ &alu_op, &alu_op, &alu_op, &alu_op,
+
+/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/
+/*50*/ &store_op, &store_op, &store_op, &store_op,
+/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/
+ &store_op, &store_op, &store_op, &store_op,
+/* POP EAX POP ECX POP EDX POP EBX*/
+ &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op,
+/* POP ESP POP EBP POP ESI POP EDI*/
+ &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op,
+
+/* PUSHA POPA BOUND ARPL*/
+/*60*/ &pusha_op, &popa_op, &bound_op, &arpl_op,
+ INVALID, INVALID, INVALID, INVALID,
+/* PUSH imm IMUL PUSH imm IMUL*/
+ &push_imm_op, &mul_op, &push_imm_op, &mul_op,
+/* INSB INSW OUTSB OUTSW*/
+ &ins_op, &ins_op, &outs_op, &outs_op,
+
+/* Jxx*/
+/*70*/ &branch_op, &branch_op, &branch_op, &branch_op,
+ &branch_op, &branch_op, &branch_op, &branch_op,
+ &branch_op, &branch_op, &branch_op, &branch_op,
+ &branch_op, &branch_op, &branch_op, &branch_op,
+
+/*80*/ INVALID, INVALID, INVALID, INVALID,
+/* TEST TEST XCHG XCHG*/
+ &alu_op, &alu_op, &xchg_op, &xchg_op,
+/* MOV MOV MOV MOV*/
+ &store_op, &store_op, &load_op, &load_op,
+/* MOV from seg LEA MOV to seg POP*/
+ &alu_op, &alu0_op, &mov_seg_reg_op, &pop_reg_op,
+
+/* NOP XCHG XCHG XCHG*/
+/*90*/ &alu_op, &xchg_op, &xchg_op, &xchg_op,
+/* XCHG XCHG XCHG XCHG*/
+ &xchg_op, &xchg_op, &xchg_op, &xchg_op,
+/* CBW CWD CALL far WAIT*/
+ &alu_op, &alu0_op, &call_far_op, &alu_op,
+/* PUSHF POPF SAHF LAHF*/
+ &pushf_op, &popf_op, &alu_op, &alu_op,
+
+/* MOV MOV MOV MOV*/
+/*a0*/ &load_op, &load_op, &store_op, &store_op,
+/* MOVSB MOVSW CMPSB CMPSW*/
+ &movs_op, &movs_op, &cmps_op, &cmps_op,
+/* TEST TEST STOSB STOSW*/
+ &alu_op, &alu_op, &stos_op, &stos_op,
+/* LODSB LODSW SCASB SCASW*/
+ &lods_op, &lods_op, &scas_op, &scas_op,
+
+/* MOV*/
+/*b0*/ &alu_op, &alu_op, &alu_op, &alu_op,
+ &alu_op, &alu_op, &alu_op, &alu_op,
+ &alu_op, &alu_op, &alu_op, &alu_op,
+ &alu_op, &alu_op, &alu_op, &alu_op,
+
+/* RET imm RET*/
+/*c0*/ INVALID, INVALID, &reti_op, &ret_op,
+/* LES LDS MOV MOV*/
+ &lss_op, &lss_op, &store_op, &store_op,
+/* ENTER LEAVE RETF RETF*/
+ &enter_op, &leave_op, &retf_op, &retf_op,
+/* INT3 INT INTO IRET*/
+ &int_op, &int_op, &int_op, &iret_op,
+
+
+/*d0*/ INVALID, INVALID, INVALID, INVALID,
+/* AAM AAD SETALC XLAT*/
+ &aam_op, &aad_op, &alu_op, &xlat_op,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+/* LOOPNE LOOPE LOOP JCXZ*/
+/*e0*/ &loop_op, &loop_op, &loop_op, &loop_op,
+/* IN AL IN AX OUT_AL OUT_AX*/
+ &io_op, &io_op, &io_op, &io_op,
+/* CALL JMP JMP JMP*/
+ &store_op, &branch_op, &jmp_far_op, &branch_op,
+/* IN AL IN AX OUT_AL OUT_AX*/
+ &io_op, &io_op, &io_op, &io_op,
+
+/* REPNE REPE*/
+/*f0*/ INVALID, INVALID, INVALID, INVALID,
+/* HLT CMC*/
+ &alu4_op, &alu_op, INVALID, INVALID,
+/* CLC STC CLI STI*/
+ &alu_op, &alu_op, &cli_op, &sti_op,
+/* CLD STD INCDEC*/
+ &alu4_op, &alu4_op, &alu_op, INVALID
+};
+
+static const p6_instruction_t *opcode_timings_0f[256] =
+{
+/*00*/ &alu6_op, &alu6_op, &alu6_op, &alu6_op,
+ INVALID, &alu6_op, &alu6_op, INVALID,
+ &invd_op, &wbinvd_op, INVALID, INVALID,
+ INVALID, &load_op, INVALID, INVALID,
+
+/*10*/ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+/*20*/ &alu6_op, &alu6_op, &alu6_op, &alu6_op,
+ &alu6_op, &alu6_op, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+/*30*/ &alu6_op, &alu6_op, &alu6_op, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+/*40*/ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+/*50*/ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+/*60*/ &load_mmx_op, &load_mmx_op, &load_mmx_op, &load_mmx_op,
+ &load_mmx_op, &load_mmx_op, &load_mmx_op, &load_mmx_op,
+ &load_mmx_op, &load_mmx_op, &load_mmx_op, &load_mmx_op,
+ INVALID, INVALID, &load_op, &load_op,
+
+/*70*/ INVALID, &load_mmx_shift_op, &load_mmx_shift_op, &load_mmx_shift_op,
+ &load_mmx_op, &load_mmx_op, &load_mmx_op, &emms_op,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, &store_op, &store_op,
+
+/*80*/ &branch_op, &branch_op, &branch_op, &branch_op,
+ &branch_op, &branch_op, &branch_op, &branch_op,
+ &branch_op, &branch_op, &branch_op, &branch_op,
+ &branch_op, &branch_op, &branch_op, &branch_op,
+
+/*90*/ &alu_op, &alu_op, &alu_op, &alu_op,
+ &alu_op, &alu_op, &alu_op, &alu_op,
+ &alu_op, &alu_op, &alu_op, &alu_op,
+ &alu_op, &alu_op, &alu_op, &alu_op,
+
+/*a0*/ &push_seg_op, &mov_seg_mem_op, &cpuid_op, &load_alu_op,
+ &alu_store_op, &alu_store_op, INVALID, INVALID,
+ &push_seg_op, &mov_seg_mem_op, INVALID, &load_alu_op,
+ &alu_store_op, &alu_store_op, INVALID, &mul_op,
+
+/*b0*/ &cmpxchg_op, &cmpxchg_op, &lss_op, &load_alu_op,
+ &lss_op, &lss_op, &load_alu_op, &load_alu_op,
+ INVALID, INVALID, &load_alu_op, &load_alu_op,
+ &load_bsx_op, &load_bsx_op, &load_alu_op, &load_alu_op,
+
+/*c0*/ &alu_store_op, &alu_store_op, INVALID, INVALID,
+ INVALID, INVALID, INVALID, &cmpxchg_op,
+ &bswap_op, &bswap_op, &bswap_op, &bswap_op,
+ &bswap_op, &bswap_op, &bswap_op, &bswap_op,
+
+/*d0*/ INVALID, &load_mmx_shift_op, &load_mmx_shift_op, &load_mmx_shift_op,
+ INVALID, &load_mmx_mul_op, INVALID, INVALID,
+ &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op,
+ &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op,
+
+/*e0*/ &load_mmx_op, &load_mmx_shift_op, &load_mmx_shift_op, INVALID,
+ INVALID, &load_mmx_mul_op, INVALID, INVALID,
+ &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op,
+ &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op,
+
+/*f0*/ INVALID, &load_mmx_shift_op, &load_mmx_shift_op, &load_mmx_shift_op,
+ INVALID, &load_mmx_mul_op, INVALID, INVALID,
+ &load_mmx_op, &load_mmx_op, &load_mmx_op, INVALID,
+ &load_mmx_op, &load_mmx_op, &load_mmx_op, INVALID,
+};
+static const p6_instruction_t *opcode_timings_0f_mod3[256] =
+{
+/*00*/ &alu6_op, &alu6_op, &alu6_op, &alu6_op,
+ INVALID, &alu6_op, &alu6_op, INVALID,
+ &invd_op, &wbinvd_op, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+/*10*/ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+/*20*/ &alu6_op, &alu6_op, &alu6_op, &alu6_op,
+ &alu6_op, &alu6_op, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+/*30*/ &alu6_op, &alu6_op, &alu6_op, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+/*40*/ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+/*50*/ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+/*60*/ &mmx_op, &mmx_op, &mmx_op, &mmx_op,
+ &mmx_op, &mmx_op, &mmx_op, &mmx_op,
+ &mmx_op, &mmx_op, &mmx_op, &mmx_op,
+ INVALID, INVALID, &mmx_op, &mmx_op,
+
+/*70*/ INVALID, &mmx_shift_op, &mmx_shift_op, &mmx_shift_op,
+ &mmx_op, &mmx_op, &mmx_op, &emms_op,
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, &mmx_op, &mmx_op,
+
+/*80*/ &branch_op, &branch_op, &branch_op, &branch_op,
+ &branch_op, &branch_op, &branch_op, &branch_op,
+ &branch_op, &branch_op, &branch_op, &branch_op,
+ &branch_op, &branch_op, &branch_op, &branch_op,
+
+/*90*/ &alu_op, &alu_op, &alu_op, &alu_op,
+ &alu_op, &alu_op, &alu_op, &alu_op,
+ &alu_op, &alu_op, &alu_op, &alu_op,
+ &alu_op, &alu_op, &alu_op, &alu_op,
+
+/*a0*/ &push_seg_op, &mov_seg_mem_op, &cpuid_op, &alu_op,
+ &alu_op, &alu_op, INVALID, INVALID,
+ &push_seg_op, &mov_seg_mem_op, INVALID, &alu_op,
+ &alu_op, &alu_op, INVALID, &mul_op,
+
+/*b0*/ &cmpxchg_op, &cmpxchg_op, &lss_op, &alu_op,
+ &lss_op, &lss_op, &alu_op, &alu_op,
+ INVALID, INVALID, &alu_op, &alu_op,
+ &bsx_op, &bsx_op, &alu_op, &alu_op,
+
+/*c0*/ &alu_op, &alu_op, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ &bswap_op, &bswap_op, &bswap_op, &bswap_op,
+ &bswap_op, &bswap_op, &bswap_op, &bswap_op,
+
+/*d0*/ INVALID, &mmx_shift_op, &mmx_shift_op, &mmx_shift_op,
+ INVALID, &mmx_mul_op, INVALID, INVALID,
+ &mmx_op, &mmx_op, INVALID, &mmx_op,
+ &mmx_op, &mmx_op, INVALID, &mmx_op,
+
+/*e0*/ &mmx_op, &mmx_shift_op, &mmx_shift_op, INVALID,
+ INVALID, &mmx_mul_op, INVALID, INVALID,
+ &mmx_op, &mmx_op, INVALID, &mmx_op,
+ &mmx_op, &mmx_op, INVALID, &mmx_op,
+
+/*f0*/ INVALID, &mmx_shift_op, &mmx_shift_op, &mmx_shift_op,
+ INVALID, &mmx_mul_op, INVALID, INVALID,
+ &mmx_op, &mmx_op, &mmx_op, INVALID,
+ &mmx_op, &mmx_op, &mmx_op, INVALID,
+};
+
+static const p6_instruction_t *opcode_timings_shift[8] =
+{
+ &alu0_store_op, &alu0_store_op, &rcx_store_op, &rcx_store_op,
+ &alu0_store_op, &alu0_store_op, &alu0_store_op, &alu0_store_op
+};
+static const p6_instruction_t *opcode_timings_shift_mod3[8] =
+{
+ &alu0_op, &alu0_op, &rcx_op, &rcx_op,
+ &alu0_op, &alu0_op, &alu0_op, &alu0_op
+};
+
+static const p6_instruction_t *opcode_timings_8x[8] =
+{
+ &alu_store_op, &alu_store_op, &aluc_store_op, &aluc_store_op,
+ &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op,
+};
+static const p6_instruction_t *opcode_timings_8x_mod3[8] =
+{
+ &alu_op, &alu_op, &aluc_op, &aluc_op,
+ &alu_op, &alu_op, &alu_op, &alu_op,
+};
+
+static const p6_instruction_t *opcode_timings_f6[8] =
+{
+/* TST NOT NEG*/
+ &load_alu_op, INVALID, &alu_store_op, &alu_store_op,
+/* MUL IMUL DIV IDIV*/
+ &mul_mem_op, &mul_mem_op, &div16_mem_op, &div16_mem_op,
+};
+static const p6_instruction_t *opcode_timings_f6_mod3[8] =
+{
+/* TST NOT NEG*/
+ &alu_op, INVALID, &alu_op, &alu_op,
+/* MUL IMUL DIV IDIV*/
+ &mul_op, &mul_op, &div16_op, &div16_op,
+};
+static const p6_instruction_t *opcode_timings_f7[8] =
+{
+/* TST NOT NEG*/
+ &load_alu_op, INVALID, &alu_store_op, &alu_store_op,
+/* MUL IMUL DIV IDIV*/
+ &mul_mem_op, &mul_mem_op, &div32_mem_op, &div32_mem_op,
+};
+static const p6_instruction_t *opcode_timings_f7_mod3[8] =
+{
+/* TST NOT NEG*/
+ &alu_op, INVALID, &alu_op, &alu_op,
+/* MUL IMUL DIV IDIV*/
+ &mul_op, &mul_op, &div32_op, &div32_op,
+};
+static const p6_instruction_t *opcode_timings_ff[8] =
+{
+/* INC DEC CALL CALL far*/
+ &alu_store_op, &alu_store_op, &store_op, &load_call_far_op,
+/* JMP JMP far PUSH*/
+ &branch_op, &load_jmp_far_op, &push_mem_op, INVALID
+};
+static const p6_instruction_t *opcode_timings_ff_mod3[8] =
+{
+/* INC DEC CALL CALL far*/
+ &alu_op, &alu_op, &store_op, &call_far_op,
+/* JMP JMP far PUSH*/
+ &branch_op, &load_jmp_far_op, &push_mem_op, INVALID
+};
+
+static const p6_instruction_t *opcode_timings_d8[8] =
+{
+/* FADDs FMULs FCOMs FCOMPs*/
+ &load_faddsub_op, &load_fmul_op, &fcom_op, &load_fcom_op,
+/* FSUBs FSUBRs FDIVs FDIVRs*/
+ &load_faddsub_op, &load_faddsub_op, &fdiv_mem_op, &fdiv_mem_op,
+};
+static const p6_instruction_t *opcode_timings_d8_mod3[8] =
+{
+/* FADD FMUL FCOM FCOMP*/
+ &faddsub_op, &fmul_op, &fcom_op, &fcom_op,
+/* FSUB FSUBR FDIV FDIVR*/
+ &faddsub_op, &faddsub_op, &fdiv_op, &fdiv_op,
+};
+
+static const p6_instruction_t *opcode_timings_d9[8] =
+{
+/* FLDs FSTs FSTPs*/
+ &load_op, INVALID, &store_op, &store_op,
+/* FLDENV FLDCW FSTENV FSTCW*/
+ &flde_op, &fldcw_op, &fste_op, &fstsw_mem_op
+};
+static const p6_instruction_t *opcode_timings_d9_mod3[64] =
+{
+ /*FLD*/
+ &float_op, &float_op, &float_op, &float_op,
+ &float_op, &float_op, &float_op, &float_op,
+ /*FXCH*/
+ &fxch_op, &fxch_op, &fxch_op, &fxch_op,
+ &fxch_op, &fxch_op, &fxch_op, &fxch_op,
+ /*FNOP*/
+ &float_op, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+ /*FSTP*/
+ &float_op, &float_op, &float_op, &float_op,
+ &float_op, &float_op, &float_op, &float_op,
+/* opFCHS opFABS*/
+ &float_op, &float_op, INVALID, INVALID,
+/* opFTST opFXAM*/
+ &float_op, &float_op, INVALID, INVALID,
+/* opFLD1 opFLDL2T opFLDL2E opFLDPI*/
+ &float_op, &float_op, &float_op, &float_op,
+/* opFLDEG2 opFLDLN2 opFLDZ*/
+ &float_op, &float_op, &float_op, INVALID,
+/* opF2XM1 opFYL2X opFPTAN opFPATAN*/
+ &fsin_op, &fsin_op, &fsin_op, &fsin_op,
+/* opFDECSTP opFINCSTP,*/
+ INVALID, INVALID, &float_op, &float_op,
+/* opFPREM opFSQRT opFSINCOS*/
+ &fdiv_op, INVALID, &fsqrt_op, &fsin_op,
+/* opFRNDINT opFSCALE opFSIN opFCOS*/
+ &float_op, &fdiv_op, &fsin_op, &fsin_op
+};
+
+static const p6_instruction_t *opcode_timings_da[8] =
+{
+/* FIADDl FIMULl FICOMl FICOMPl*/
+ &load_fi_op, &load_fi_op, &load_fcom_op, &load_fcom_op,
+/* FISUBl FISUBRl FIDIVl FIDIVRl*/
+ &load_fi_op, &load_fi_op, &load_fi_op, &load_fi_op,
+};
+static const p6_instruction_t *opcode_timings_da_mod3[8] =
+{
+ INVALID, INVALID, INVALID, INVALID,
+/* FCOMPP*/
+ INVALID, &fcompp_op, INVALID, INVALID
+};
+
+static const p6_instruction_t *opcode_timings_db[8] =
+{
+/* FLDil FSTil FSTPil*/
+ &fild_op, INVALID, &fist_op, &fist_op,
+/* FLDe FSTPe*/
+ INVALID, &flde_op, INVALID, &fste_op
+};
+static const p6_instruction_t *opcode_timings_db_mod3[64] =
+{
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+/* opFNOP opFCLEX opFINIT*/
+ INVALID, &float_op, &float_op, &float_op,
+/* opFNOP opFNOP*/
+ &float_op, &float_op, INVALID, INVALID,
+
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+
+ INVALID, INVALID, INVALID, INVALID,
+ INVALID, INVALID, INVALID, INVALID,
+};
+
+static const p6_instruction_t *opcode_timings_dc[8] =
+{
+/* FADDd FMULd FCOMd FCOMPd*/
+ &load_faddsub_op, &load_fmul_op, &load_fcom_op, &load_fcom_op,
+/* FSUBd FSUBRd FDIVd FDIVRd*/
+ &load_faddsub_op, &load_faddsub_op, &fdiv_mem_op, &fdiv_mem_op,
+};
+static const p6_instruction_t *opcode_timings_dc_mod3[8] =
+{
+/* opFADDr opFMULr*/
+ &faddsub_op, &fmul_op, INVALID, INVALID,
+/* opFSUBRr opFSUBr opFDIVRr opFDIVr*/
+ &faddsub_op, &faddsub_op, &fdiv_op, &fdiv_op
+};
+
+static const p6_instruction_t *opcode_timings_dd[8] =
+{
+/* FLDd FSTd FSTPd*/
+ &load_op, INVALID, &store_op, &store_op,
+/* FRSTOR FSAVE FSTSW*/
+ &frstor_op, INVALID, &fsave_op, &fstsw_mem_op
+};
+static const p6_instruction_t *opcode_timings_dd_mod3[8] =
+{
+/* FFFREE FST FSTP*/
+ &float_op, INVALID, &float_op, &float_op,
+/* FUCOM FUCOMP*/
+ &float_op, &float_op, INVALID, INVALID
+};
+
+static const p6_instruction_t *opcode_timings_de[8] =
+{
+/* FIADDw FIMULw FICOMw FICOMPw*/
+ &load_fi_op, &load_fi_op, &load_fcom_op, &load_fcom_op,
+/* FISUBw FISUBRw FIDIVw FIDIVRw*/
+ &load_fi_op, &load_fi_op, &load_fi_op, &load_fi_op,
+};
+static const p6_instruction_t *opcode_timings_de_mod3[8] =
+{
+/* FADDP FMULP FCOMPP*/
+ &faddsub_op, &fmul_op, INVALID, &fcompp_op,
+/* FSUBP FSUBRP FDIVP FDIVRP*/
+ &faddsub_op, &faddsub_op, &fdiv_op, &fdiv_op,
+};
+
+static const p6_instruction_t *opcode_timings_df[8] =
+{
+/* FILDiw FISTiw FISTPiw*/
+ &fild_op, INVALID, &fist_op, &fist_op,
+/* FILDiq FBSTP FISTPiq*/
+ INVALID, &fild_op, &fbstp_op, &fist_op,
+};
+static const p6_instruction_t *opcode_timings_df_mod3[8] =
+{
+ INVALID, INVALID, INVALID, INVALID,
+/* FSTSW AX*/
+ &fstsw_ax_op, INVALID, INVALID, INVALID
+};
+
+
+static uint8_t last_prefix;
+static int prefixes;
+
+static int decode_timestamp;
+static int last_complete_timestamp;
+
+typedef struct p6_unit_t
+{
+ const uint32_t uop_mask;
+ const int port;
+ int first_available_cycle;
+} p6_unit_t;
+
+enum
+{
+ UNIT_INT0 = 0,
+ UNIT_INT1,
+ UNIT_FPU,
+ UNIT_MMX_ADD,
+ UNIT_MMX_MUL,
+ UNIT_JUMP,
+ UNIT_LOAD,
+ UNIT_STORE_ADDR,
+ UNIT_STORE_DATA
+};
+
+/*Each port can only be used once per clock*/
+typedef struct p6_port_t
+{
+ uint32_t unit_mask;
+} p6_port_t;
+
+static int port_last_timestamps[5];
+
+static const p6_port_t ports[] =
+{
+ {UNIT_INT0 | UNIT_FPU | UNIT_MMX_MUL},
+ {UNIT_INT1 | UNIT_MMX_ADD | UNIT_JUMP},
+ {UNIT_LOAD},
+ {UNIT_STORE_ADDR},
+ {UNIT_STORE_DATA}
+};
+const int nr_ports = (sizeof(ports) / sizeof(p6_port_t));
+
+static p6_unit_t units[] =
+{
+ [UNIT_INT0] = {.uop_mask = (1 << UOP_ALU0) | (1 << UOP_ALU0_SEG) | (1 << UOP_ALU01), .port = 0}, /*Integer 0*/
+ [UNIT_INT1] = {.uop_mask = (1 << UOP_ALU1) | (1 << UOP_ALU01), .port = 1}, /*Integer 1*/
+ [UNIT_FPU] = {.uop_mask = 1 << UOP_FLOAT, .port = 0},
+ [UNIT_MMX_ADD] = {.uop_mask = 0, .port = 1},
+ [UNIT_MMX_MUL] = {.uop_mask = 0, .port = 0},
+ [UNIT_JUMP] = {.uop_mask = 1 << UOP_BRANCH, .port = 1},
+ [UNIT_LOAD] = {.uop_mask = 1 << UOP_LOAD, .port = 2},
+ [UNIT_STORE_ADDR] = {.uop_mask = 1 << UOP_STOREADDR, .port = 3},
+ [UNIT_STORE_DATA] = {.uop_mask = 1 << UOP_STOREDATA, .port = 4}
+};
+const int nr_units = (sizeof(units) / sizeof(p6_unit_t));
+
+static int rat_timestamp = 0;
+static int rat_uops = 0;
+
+static int uop_run(const p6_uop_t *uop, int decode_time)
+{
+ int c;
+ p6_unit_t *best_unit = NULL;
+ int best_start_cycle = 99999;
+
+ /*Peak of 3 uOPs from decode to RAT per cycle*/
+ if (decode_time < rat_timestamp)
+ decode_time = rat_timestamp;
+ else if (decode_time > rat_timestamp)
+ {
+ rat_timestamp = decode_time;
+ rat_uops = 0;
+ }
+
+ rat_uops++;
+ if (rat_uops == 3)
+ {
+ rat_timestamp++;
+ rat_uops = 0;
+ }
+
+
+ /*Find execution unit for this uOP*/
+ for (c = 0; c < nr_units; c++)
+ {
+ p6_unit_t *unit = &units[c];
+ if (unit->uop_mask & (1 << uop->type))
+ {
+ int start_cycle = MAX(unit->first_available_cycle,
+ port_last_timestamps[units[c].port]);
+
+ if (start_cycle < best_start_cycle)
+ {
+ best_unit = unit;
+ best_start_cycle = start_cycle;
+ }
+ }
+ }
+ if (!best_unit)
+ fatal("uop_run: can not find execution unit %x\n", uop->type);
+
+ if (cpu_s->cpu_type == CPU_PENTIUMPRO && uop->type == UOP_ALU0_SEG)
+ {
+ /*Pentium Pro will flush pipeline on a segment load. Find last
+ execution unit to complete, then set earliest start times on
+ _all_ execution units to after this point*/
+ int last_start_cycle = 0;
+
+ for (c = 0; c < nr_units; c++)
+ {
+ p6_unit_t *unit = &units[c];
+ int start_cycle = unit->first_available_cycle;
+
+ if (start_cycle > last_start_cycle)
+ last_start_cycle = start_cycle;
+ }
+ for (c = 0; c < nr_units; c++)
+ units[c].first_available_cycle = last_start_cycle+1;
+ }
+ if (best_start_cycle < decode_time)
+ best_start_cycle = decode_time;
+ best_unit->first_available_cycle = best_start_cycle + uop->throughput;
+ port_last_timestamps[best_unit->port] = best_start_cycle + 1;
+
+ return best_start_cycle + uop->throughput;
+// return decode_time+1;
+}
+
+/*The P6 decoder can decode up to three instructions per clock
+ First can be up to 4 uOPs
+ Second and third must be 1 uOP each
+ Up to 16 bytes per cycle
+ 1 cycle per prefix beyond 1 prefix
+ 0x66 causes delays if instruction has immediate
+ 0x67 causes delays if modr/m present (and mod != 3)
+*/
+static struct
+{
+ int nr_ins;
+ int nr_uops;
+ const p6_uop_t *uops[6];
+ /*Earliest time a uop can start. If the timestamp is -1, then the uop is
+ part of a dependency chain and the start time is the completion time of
+ the previous uop*/
+ int earliest_start[6];
+} decode_buffer;
+
+#define NR_REGS 8
+/*Timestamp of when last operation on an integer register completed*/
+static int reg_available_timestamp[NR_REGS];
+/*Timestamp of when last operation on an FPU register completed*/
+static int fpu_st_timestamp[8];
+/*Completion time of the last uop to be processed. Used to calculate timing of
+ dependent uop chains*/
+static int last_uop_timestamp = 0;
+
+static int ifetch_length = 0;
+static int has_66_prefix, has_67_prefix;
+
+static void decode_flush()
+{
+ int c;
+ int uop_timestamp = 0;
+
+ /*Ensure that uops can not be submitted before they have been decoded*/
+ if (decode_timestamp > last_uop_timestamp)
+ last_uop_timestamp = decode_timestamp;
+
+ /*Submit uops to execution units, and determine the latest completion time*/
+ for (c = 0; c < decode_buffer.nr_uops; c++)
+ {
+ int start_timestamp;
+
+// pclog("uOP %i, %p\n", c, decode_buffer.uops[c]);
+
+ if (decode_buffer.earliest_start[c] == -1)
+ start_timestamp = last_uop_timestamp;
+ else
+ start_timestamp = decode_buffer.earliest_start[c];
+
+ last_uop_timestamp = uop_run(decode_buffer.uops[c], start_timestamp);
+ if (last_uop_timestamp > uop_timestamp)
+ uop_timestamp = last_uop_timestamp;
+ }
+
+ /*Calculate opquad completion time. Since opquads complete in order, it
+ must be after the last completion.*/
+ if (uop_timestamp <= last_complete_timestamp)
+ last_complete_timestamp = last_complete_timestamp + 1;
+ else
+ last_complete_timestamp = uop_timestamp;
+
+ decode_timestamp++;
+ decode_buffer.nr_uops = 0;
+ decode_buffer.nr_ins = 0;
+ ifetch_length = 0;
+}
+
+/*The instruction is only of interest here if it's longer than 8 bytes, as that's the
+ limit on P6 short decoding*/
+static int codegen_timing_instr_length(uint64_t deps, uint32_t fetchdat, int op_32)
+{
+ int len = prefixes + 1; /*Opcode*/
+ if (deps & MODRM)
+ {
+ len++; /*ModR/M*/
+ if (deps & HAS_IMM8)
+ len++;
+ if (deps & HAS_IMM1632)
+ len += (op_32 & 0x100) ? 4 : 2;
+
+ if (op_32 & 0x200)
+ {
+ if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0)
+ {
+ /* Has SIB*/
+ len++;
+ if ((fetchdat & 0xc0) == 0x40)
+ len++;
+ else if ((fetchdat & 0xc0) == 0x80)
+ len += 4;
+ else if ((fetchdat & 0x700) == 0x500)
+ len += 4;
+ }
+ else
+ {
+ if ((fetchdat & 0xc0) == 0x40)
+ len++;
+ else if ((fetchdat & 0xc0) == 0x80)
+ len += 4;
+ else if ((fetchdat & 0xc7) == 0x05)
+ len += 4;
+ }
+ }
+ else
+ {
+ if ((fetchdat & 0xc0) == 0x40)
+ len++;
+ else if ((fetchdat & 0xc0) == 0x80)
+ len += 2;
+ else if ((fetchdat & 0xc7) == 0x06)
+ len += 2;
+ }
+ }
+
+ return len;
+}
+
+static void decode_instruction(const p6_instruction_t *ins, uint64_t deps, uint32_t fetchdat, int op_32, uint32_t op_pc, int bit8)
+{
+ uint32_t regmask_required;
+ uint32_t regmask_modified;
+ int c, d;
+ int earliest_start;
+ int instr_length = codegen_timing_instr_length(deps, fetchdat, op_32);
+
+ if (has_66_prefix && (deps & HAS_IMM1632))
+ decode_timestamp += 2;
+ if (has_67_prefix && (deps & MODRM))
+ decode_timestamp += 4;
+
+ earliest_start = decode_timestamp;
+
+ /*Generate input register mask, and determine the earliest time this
+ instruction can start. This is not accurate, as this is calculated per
+ x86 instruction when it should be handled per uop*/
+ regmask_required = get_dstdep_mask(deps, fetchdat, bit8);
+ regmask_required |= get_addr_regmask(deps, fetchdat, op_32);
+ for (c = 0; c < 8; c++)
+ {
+ if (regmask_required & (1 << c))
+ {
+ if (reg_available_timestamp[c] > decode_timestamp)
+ earliest_start = reg_available_timestamp[c];
+ }
+ }
+ if ((deps & FPU_RW_ST0) && fpu_st_timestamp[0] > decode_timestamp)
+ earliest_start = fpu_st_timestamp[0];
+ if ((deps & FPU_RW_ST1) && fpu_st_timestamp[1] > decode_timestamp)
+ earliest_start = fpu_st_timestamp[1];
+ if ((deps & FPU_RW_STREG))
+ {
+ int reg = fetchdat & 7;
+
+ if (fpu_st_timestamp[reg] > decode_timestamp)
+ earliest_start = fpu_st_timestamp[reg];
+ }
+
+// pclog("ins->nr_uops=%i decode_buffer.nr_uops=%i decode_buffer.nr_ins=%i instr_length=%i\n", ins->nr_uops, decode_buffer.nr_uops, decode_buffer.nr_ins, instr_length);
+
+ /*Can only decode 16 bytes per cycle*/
+ if ((ifetch_length + instr_length) > 16)
+ decode_flush();
+ else
+ ifetch_length += instr_length;
+
+ if (ins->nr_uops > 4)
+ {
+// pclog("Long decode\n");
+ /*Multi-cycle decode (> 4 uOPs) instruction*/
+ if (decode_buffer.nr_ins)
+ decode_flush();
+
+ d = 0;
+
+ for (c = 0; c < ins->nr_uops; c++)
+ {
+ decode_buffer.uops[d] = &ins->uop[c];
+ if (c == 0)
+ decode_buffer.earliest_start[d] = earliest_start;
+ else
+ decode_buffer.earliest_start[d] = -1;
+ d++;
+
+ if (d == 4)
+ {
+ d = 0;
+ decode_buffer.nr_uops = 4;
+ decode_flush();
+ }
+ }
+ if (d)
+ {
+ decode_buffer.nr_uops = d;
+ decode_flush();
+ }
+ }
+ else if (ins->nr_uops > 1 || instr_length > 8)
+ {
+// pclog("Mid decode\n");
+ /*Long (> 1 uOPs) instruction*/
+ if (decode_buffer.nr_ins)
+ decode_flush();
+
+ decode_buffer.nr_uops = ins->nr_uops;
+
+ for (c = 0; c < ins->nr_uops; c++)
+ {
+ decode_buffer.uops[c] = &ins->uop[c];
+ if (c == 0)
+ decode_buffer.earliest_start[c] = earliest_start;
+ else
+ decode_buffer.earliest_start[c] = -1;
+ }
+ decode_buffer.nr_ins++;
+ }
+ else if (ins->nr_uops == 1)
+ {
+// pclog("Short decode\n");
+ /*Short (1 uOP) instruction*/
+ decode_buffer.uops[decode_buffer.nr_uops] = &ins->uop[0];
+ decode_buffer.earliest_start[decode_buffer.nr_uops] = earliest_start;
+ decode_buffer.nr_ins++;
+ decode_buffer.nr_uops++;
+
+ if (decode_buffer.nr_ins == 3)
+ decode_flush();
+ }
+
+ /*Update write timestamps for any output registers*/
+ regmask_modified = get_dstdep_mask(deps, fetchdat, bit8);
+ for (c = 0; c < 8; c++)
+ {
+ if (regmask_modified & (1 << c))
+ reg_available_timestamp[c] = last_complete_timestamp;
+ }
+ if (deps & FPU_POP)
+ {
+ for (c = 0; c < 7; c++)
+ fpu_st_timestamp[c] = fpu_st_timestamp[c+1];
+ fpu_st_timestamp[7] = 0;
+ }
+ if (deps & FPU_POP2)
+ {
+ for (c = 0; c < 6; c++)
+ fpu_st_timestamp[c] = fpu_st_timestamp[c+2];
+ fpu_st_timestamp[6] = fpu_st_timestamp[7] = 0;
+ }
+ if (deps & FPU_PUSH)
+ {
+ for (c = 0; c < 7; c++)
+ fpu_st_timestamp[c+1] = fpu_st_timestamp[c];
+ fpu_st_timestamp[0] = 0;
+ }
+ if (deps & FPU_WRITE_ST0)
+ fpu_st_timestamp[0] = last_complete_timestamp;
+ if (deps & FPU_WRITE_ST1)
+ fpu_st_timestamp[1] = last_complete_timestamp;
+ if (deps & FPU_WRITE_STREG)
+ {
+ int reg = fetchdat & 7;
+ if (deps & FPU_POP)
+ reg--;
+ if (reg >= 0 &&
+ !(reg == 0 && (deps & FPU_WRITE_ST0)) &&
+ !(reg == 1 && (deps & FPU_WRITE_ST1)))
+ fpu_st_timestamp[reg] = last_complete_timestamp;
+ }
+}
+
+void codegen_timing_p6_block_start()
+{
+ int c;
+
+ for (c = 0; c < nr_units; c++)
+ units[c].first_available_cycle = 0;
+
+ decode_timestamp = 0;
+ last_complete_timestamp = 0;
+
+ rat_timestamp = 0;
+ rat_uops = 0;
+
+ for (c = 0; c < 5; c++)
+ port_last_timestamps[c] = 0;
+
+ for (c = 0; c < NR_REGS; c++)
+ reg_available_timestamp[c] = 0;
+ for (c = 0; c < 8; c++)
+ fpu_st_timestamp[c] = 0;
+
+ ifetch_length = 0;
+}
+
+void codegen_timing_p6_start()
+{
+// units = p6_units;
+// nr_units = NR_P6_UNITS;
+ last_prefix = 0;
+ prefixes = 0;
+ has_66_prefix = 0;
+ has_67_prefix = 0;
+}
+
+/*Prefixes :
+ - first is free
+ - operand size prefix has a penalty of 'a few clocks' if instruction has 16 or
+ 32 bit immediate
+ - address size prefix has penalty if instruction has explicit memory operand*/
+void codegen_timing_p6_prefix(uint8_t prefix, uint32_t fetchdat)
+{
+ if (last_prefix) /*First prefix is free*/
+ decode_timestamp++;
+ if (prefix == 0x66)
+ has_66_prefix = 1;
+ if (prefix == 0x67)
+ has_67_prefix = 1;
+
+ last_prefix = prefix;
+ prefixes++;
+}
+
+void codegen_timing_p6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc)
+{
+ const p6_instruction_t **ins_table;
+ uint64_t *deps;
+ int mod3 = ((fetchdat & 0xc0) == 0xc0);
+ int old_last_complete_timestamp = last_complete_timestamp;
+ int bit8 = !(opcode & 1);
+
+// pclog("timing_opcode %02x\n", opcode);
+ switch (last_prefix)
+ {
+ case 0x0f:
+ ins_table = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f;
+ deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f;
+// pclog("timings 0f\n");
+ break;
+
+ case 0xd8:
+ ins_table = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8;
+ deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8;
+ opcode = (opcode >> 3) & 7;
+// pclog("timings d8\n");
+ break;
+ case 0xd9:
+ ins_table = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9;
+ deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9;
+ opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7;
+// pclog("timings d9\n");
+ break;
+ case 0xda:
+ ins_table = mod3 ? opcode_timings_da_mod3 : opcode_timings_da;
+ deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da;
+ opcode = (opcode >> 3) & 7;
+// pclog("timings da\n");
+ break;
+ case 0xdb:
+ ins_table = mod3 ? opcode_timings_db_mod3 : opcode_timings_db;
+ deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db;
+ opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7;
+// pclog("timings db\n");
+ break;
+ case 0xdc:
+ ins_table = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc;
+ deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc;
+ opcode = (opcode >> 3) & 7;
+// pclog("timings dc\n");
+ break;
+ case 0xdd:
+ ins_table = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd;
+ deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd;
+ opcode = (opcode >> 3) & 7;
+// pclog("timings dd\n");
+ break;
+ case 0xde:
+ ins_table = mod3 ? opcode_timings_de_mod3 : opcode_timings_de;
+ deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de;
+ opcode = (opcode >> 3) & 7;
+// pclog("timings de\n");
+ break;
+ case 0xdf:
+ ins_table = mod3 ? opcode_timings_df_mod3 : opcode_timings_df;
+ deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df;
+ opcode = (opcode >> 3) & 7;
+// pclog("timings df\n");
+ break;
+
+ default:
+ switch (opcode)
+ {
+ case 0x80: case 0x81: case 0x82: case 0x83:
+ ins_table = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x;
+ deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x;
+ opcode = (fetchdat >> 3) & 7;
+// pclog("timings 80 %p %p %p\n", (void *)timings, (void *)opcode_timings_mod3, (void *)opcode_timings_8x);
+ break;
+
+ case 0xc0: case 0xd0: case 0xd2:
+ case 0xc1: case 0xd1: case 0xd3:
+ ins_table = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift;
+ deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift;
+ opcode = (fetchdat >> 3) & 7;
+// pclog("timings c1\n");
+ break;
+
+ case 0xf6:
+ ins_table = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6;
+ deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6;
+ opcode = (fetchdat >> 3) & 7;
+// pclog("timings f6\n");
+ break;
+ case 0xf7:
+ ins_table = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7;
+ deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7;
+ opcode = (fetchdat >> 3) & 7;
+// pclog("timings f7\n");
+ break;
+ case 0xff:
+ ins_table = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff;
+ deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff;
+ opcode = (fetchdat >> 3) & 7;
+// pclog("timings ff\n");
+ break;
+
+ default:
+ ins_table = mod3 ? opcode_timings_mod3 : opcode_timings;
+ deps = mod3 ? opcode_deps_mod3 : opcode_deps;
+// pclog("timings normal\n");
+ break;
+ }
+ }
+
+ if (ins_table[opcode])
+ decode_instruction(ins_table[opcode], deps[opcode], fetchdat, op_32, op_pc, bit8);
+ else
+ decode_instruction(&alu01_op, 0, fetchdat, op_32, op_pc, bit8);
+ codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp);
+}
+
+void codegen_timing_p6_block_end()
+{
+ if (decode_buffer.nr_ins)
+ {
+ int old_last_complete_timestamp = last_complete_timestamp;
+ decode_flush();
+ codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp);
+ }
+// pclog("codegen_block_cycles=%i\n", codegen_block_cycles);
+}
+
+int codegen_timing_p6_jump_cycles()
+{
+ if (decode_buffer.nr_uops)
+ return 1;
+ return 0;
+}
+
+codegen_timing_t codegen_timing_p6 =
+{
+ codegen_timing_p6_start,
+ codegen_timing_p6_prefix,
+ codegen_timing_p6_opcode,
+ codegen_timing_p6_block_start,
+ codegen_timing_p6_block_end,
+ codegen_timing_p6_jump_cycles
+};
+
diff --git a/src/cpu.c b/src/cpu.c
index 42cbee1..99c0c8b 100644
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -6,7 +6,9 @@
#include "mem.h"
#include "pci.h"
#include "codegen.h"
+#include "x87_timings.h"
+int fpu_type;
uint32_t cpu_features;
static int cpu_turbo_speed, cpu_nonturbo_speed;
@@ -68,6 +70,7 @@ enum
CPUID_TSC = (1 << 4),
CPUID_MSR = (1 << 5),
CPUID_CMPXCHG8B = (1 << 8),
+ CPUID_SEP = (1 << 11),
CPUID_CMOV = (1 << 15),
CPUID_MMX = (1 << 23)
};
@@ -125,10 +128,59 @@ void cpu_set_edx()
EDX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset;
}
+int fpu_get_type(int model, int manu, int cpu, const char *internal_name)
+{
+ CPU *cpu_s = &models[model].cpu[manu].cpus[cpu];
+ const FPU *fpus = cpu_s->fpus;
+ int fpu_type = fpus[0].type;
+ int c = 0;
+
+ while (fpus[c].internal_name)
+ {
+ if (!strcmp(internal_name, fpus[c].internal_name))
+ fpu_type = fpus[c].type;
+ c++;
+ }
+
+ return fpu_type;
+}
+
+const char *fpu_get_internal_name(int model, int manu, int cpu, int type)
+{
+ CPU *cpu_s = &models[model].cpu[manu].cpus[cpu];
+ const FPU *fpus = cpu_s->fpus;
+ int c = 0;
+
+ while (fpus[c].internal_name)
+ {
+ if (fpus[c].type == type)
+ return fpus[c].internal_name;
+ c++;
+ }
+
+ return fpus[0].internal_name;
+}
+
+const char *fpu_get_name_from_index(int model, int manu, int cpu, int c)
+{
+ CPU *cpu_s = &models[model].cpu[manu].cpus[cpu];
+ const FPU *fpus = cpu_s->fpus;
+
+ return fpus[c].name;
+}
+
+int fpu_get_type_from_index(int model, int manu, int cpu, int c)
+{
+ CPU *cpu_s = &models[model].cpu[manu].cpus[cpu];
+ const FPU *fpus = cpu_s->fpus;
+
+ return fpus[c].type;
+}
+
+CPU *cpu_s;
+
void cpu_set()
{
- CPU *cpu_s;
-
if (!models[model].cpu[cpu_manufacturer].cpus)
{
/*CPU is invalid, set to default*/
@@ -143,7 +195,8 @@ void cpu_set()
is8086 = (cpu_s->cpu_type > CPU_8088);
is386 = (cpu_s->cpu_type >= CPU_386SX);
is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC);
- hasfpu = (cpu_s->cpu_type >= CPU_i486DX);
+ hasfpu = (fpu_type != FPU_NONE);
+
cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86 || cpu_s->cpu_type == CPU_Cx6x86 || cpu_s->cpu_type == CPU_Cx6x86MX || cpu_s->cpu_type == CPU_Cx6x86L || cpu_s->cpu_type == CPU_CxGX1);
cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC);
if (cpu_s->multi)
@@ -159,6 +212,7 @@ void cpu_set()
cpu_nonturbo_speed = cpu_s->rspeed;
else
cpu_nonturbo_speed = 8000000;
+ cpu_turbo = 1;
cpu_update_waitstates();
@@ -280,6 +334,7 @@ void cpu_set()
timing_misaligned = 0;
cpu_cyrix_alignment = 0;
+ cpu_CR4_mask = 0;
switch (cpu_s->cpu_type)
{
@@ -734,7 +789,7 @@ void cpu_set()
break;
case CPU_Cx6x86:
- x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f);
+ x86_setopcodes(ops_386, ops_c6x86_0f, dynarec_ops_386, dynarec_ops_c6x86_0f);
timing_rr = 1; /*register dest - register src*/
timing_rm = 1; /*register dest - memory src*/
timing_mr = 2; /*memory dest - register src*/
@@ -953,9 +1008,170 @@ void cpu_set()
codegen_timing_set(&codegen_timing_k6);
break;
+ case CPU_PENTIUMPRO:
+ x86_setopcodes(ops_386, ops_pentiumpro_0f, dynarec_ops_386, dynarec_ops_pentiumpro_0f);
+ x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16;
+ x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32;
+ x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16;
+ x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32;
+ x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16;
+ x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32;
+ x86_opcodes_da_a16 = ops_fpu_686_da_a16;
+ x86_opcodes_da_a32 = ops_fpu_686_da_a32;
+ x86_opcodes_db_a16 = ops_fpu_686_db_a16;
+ x86_opcodes_db_a32 = ops_fpu_686_db_a32;
+ x86_opcodes_df_a16 = ops_fpu_686_df_a16;
+ x86_opcodes_df_a32 = ops_fpu_686_df_a32;
+ timing_rr = 1; /*register dest - register src*/
+ timing_rm = 2; /*register dest - memory src*/
+ timing_mr = 3; /*memory dest - register src*/
+ timing_mm = 3;
+ timing_rml = 2; /*register dest - memory src long*/
+ timing_mrl = 3; /*memory dest - register src long*/
+ timing_mml = 3;
+ timing_bt = 0; /*branch taken*/
+ timing_bnt = 2; /*branch not taken*/
+ timing_int = 6;
+ timing_int_rm = 11;
+ timing_int_v86 = 54;
+ timing_int_pm = 25;
+ timing_int_pm_outer = 42;
+ timing_iret_rm = 7;
+ timing_iret_v86 = 27; /*unknown*/
+ timing_iret_pm = 10;
+ timing_iret_pm_outer = 27;
+ timing_call_rm = 4;
+ timing_call_pm = 4;
+ timing_call_pm_gate = 22;
+ timing_call_pm_gate_inner = 44;
+ timing_retf_rm = 4;
+ timing_retf_pm = 4;
+ timing_retf_pm_outer = 23;
+ timing_jmp_rm = 3;
+ timing_jmp_pm = 3;
+ timing_jmp_pm_gate = 18;
+ timing_misaligned = 3;
+ cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_CX8 | CPU_FEATURE_SYSCALL;
+ msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
+ cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE;
+ codegen_timing_set(&codegen_timing_p6);
+ break;
+
+ case CPU_PENTIUM_2:
+ case CPU_CELERON:
+ case CPU_CELERON_A:
+ x86_setopcodes(ops_386, ops_pentium2_0f, dynarec_ops_386, dynarec_ops_pentium2_0f);
+ x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16;
+ x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32;
+ x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16;
+ x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32;
+ x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16;
+ x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32;
+ x86_opcodes_da_a16 = ops_fpu_686_da_a16;
+ x86_opcodes_da_a32 = ops_fpu_686_da_a32;
+ x86_opcodes_db_a16 = ops_fpu_686_db_a16;
+ x86_opcodes_db_a32 = ops_fpu_686_db_a32;
+ x86_opcodes_df_a16 = ops_fpu_686_df_a16;
+ x86_opcodes_df_a32 = ops_fpu_686_df_a32;
+ timing_rr = 1; /*register dest - register src*/
+ timing_rm = 2; /*register dest - memory src*/
+ timing_mr = 3; /*memory dest - register src*/
+ timing_mm = 3;
+ timing_rml = 2; /*register dest - memory src long*/
+ timing_mrl = 3; /*memory dest - register src long*/
+ timing_mml = 3;
+ timing_bt = 0; /*branch taken*/
+ timing_bnt = 2; /*branch not taken*/
+ timing_int = 6;
+ timing_int_rm = 11;
+ timing_int_v86 = 54;
+ timing_int_pm = 25;
+ timing_int_pm_outer = 42;
+ timing_iret_rm = 7;
+ timing_iret_v86 = 27; /*unknown*/
+ timing_iret_pm = 10;
+ timing_iret_pm_outer = 27;
+ timing_call_rm = 4;
+ timing_call_pm = 4;
+ timing_call_pm_gate = 22;
+ timing_call_pm_gate_inner = 44;
+ timing_retf_rm = 4;
+ timing_retf_pm = 4;
+ timing_retf_pm_outer = 23;
+ timing_jmp_rm = 3;
+ timing_jmp_pm = 3;
+ timing_jmp_pm_gate = 18;
+ timing_misaligned = 3;
+ cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_CX8 | CPU_FEATURE_MMX | CPU_FEATURE_SYSCALL;
+ msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
+ cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE;
+ codegen_timing_set(&codegen_timing_p6);
+ break;
+
+ case CPU_CYRIX_III:
+ x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f);
+ timing_rr = 1; /*register dest - register src*/
+ timing_rm = 1; /*register dest - memory src*/
+ timing_mr = 1; /*memory dest - register src*/
+ timing_mm = 1;
+ timing_rml = 1; /*register dest - memory src long*/
+ timing_mrl = 1; /*memory dest - register src long*/
+ timing_mml = 1;
+ timing_bt = 1; /*branch taken*/
+ timing_bnt = 1; /*branch not taken*/
+ cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_3DNOW;
+ msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21);
+ cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
+ /*unknown*/
+ timing_int_rm = 26;
+ timing_int_v86 = 82;
+ timing_int_pm = 44;
+ timing_int_pm_outer = 71;
+ timing_iret_rm = 7;
+ timing_iret_v86 = 26;
+ timing_iret_pm = 10;
+ timing_iret_pm_outer = 26;
+ timing_call_rm = 4;
+ timing_call_pm = 15;
+ timing_call_pm_gate = 26;
+ timing_call_pm_gate_inner = 35;
+ timing_retf_rm = 4;
+ timing_retf_pm = 7;
+ timing_retf_pm_outer = 23;
+ timing_jmp_rm = 5;
+ timing_jmp_pm = 7;
+ timing_jmp_pm_gate = 17;
+ timing_misaligned = 2;
+ cpu_cyrix_alignment = 1;
+ codegen_timing_set(&codegen_timing_cyrixiii);
+ break;
+
default:
fatal("cpu_set : unknown CPU type %i\n", cpu_s->cpu_type);
}
+
+ switch (fpu_type)
+ {
+ case FPU_NONE:
+ break;
+
+ case FPU_8087:
+ x87_timings = x87_timings_8087;
+ break;
+
+ case FPU_287:
+ x87_timings = x87_timings_287;
+ break;
+
+ case FPU_287XL:
+ case FPU_387:
+ x87_timings = x87_timings_387;
+ break;
+
+ default:
+ x87_timings = x87_timings_486;
+ break;
+ }
}
void cpu_CPUID()
@@ -1451,6 +1667,132 @@ void cpu_CPUID()
break;
}
break;
+
+ case CPU_PENTIUMPRO:
+ if (!EAX)
+ {
+ EAX = 0x00000002;
+ EBX = 0x756e6547;
+ EDX = 0x49656e69;
+ ECX = 0x6c65746e;
+ }
+ else if (EAX == 1)
+ {
+ EAX = CPUID;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_SEP;
+ }
+ else if (EAX == 2)
+ {
+ EAX = 0x03020101;
+ EBX = 0;
+ ECX = 0;
+ EDX = 0x06040a42;
+ }
+ else
+ EAX = EBX = ECX = EDX = 0;
+ break;
+
+ case CPU_PENTIUM_2:
+ case CPU_CELERON:
+ case CPU_CELERON_A:
+ if (!EAX)
+ {
+ EAX = 0x00000002;
+ EBX = 0x756e6547;
+ EDX = 0x49656e69;
+ ECX = 0x6c65746e;
+ }
+ else if (EAX == 1)
+ {
+ EAX = CPUID;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_MMX | CPUID_SEP;
+ }
+ else if (EAX == 2)
+ {
+ EAX = 0x03020101;
+ EBX = 0;
+ ECX = 0;
+ if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_PENTIUM_2)
+ EDX = 0x08040c43; /*512kb L2 cache*/
+ else if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_CELERON)
+ EDX = 0x08040c40; /*No L2 cache*/
+ else
+ EDX = 0x08040c41; /*128kb L2 cache*/
+ }
+ else
+ EAX = EBX = ECX = EDX = 0;
+ break;
+
+ case CPU_CYRIX_III:
+ switch (EAX)
+ {
+ case 0:
+ EAX = 1;
+ EBX = 0x746e6543; /*CentaurHauls*/
+ ECX = 0x736c7561;
+ EDX = 0x48727561;
+ break;
+ case 1:
+ EAX = models[model].cpu[cpu_manufacturer].cpus[cpu].cpuid_model;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
+ if (cpu_has_feature(CPU_FEATURE_CX8))
+ EDX |= CPUID_CMPXCHG8B;
+ if (msr.fcr & (1 << 9))
+ EDX |= CPUID_MMX;
+ break;
+ case 0x80000000:
+ EAX = 0x80000006;
+ break;
+ case 0x80000001:
+ EAX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset;
+ EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
+ if (cpu_has_feature(CPU_FEATURE_CX8))
+ EDX |= CPUID_CMPXCHG8B;
+ if (msr.fcr & (1 << 9))
+ EDX |= CPUID_MMX;
+ if (cpu_has_feature(CPU_FEATURE_3DNOW))
+ EDX |= CPUID_3DNOW;
+ break;
+
+ case 0x80000002: /*Processor name string*/
+ if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpuid_model >= 0x670)
+ {
+ EAX = 0x20414956; /*VIA Samuel 2*/
+ EBX = 0x756d6153;
+ ECX = 0x32206c65;
+ EDX = 0x00000000;
+ }
+ else
+ {
+ EAX = 0x20414956; /*VIA SamuelM*/
+ EBX = 0x756d6153;
+ ECX = 0x004d6c65;
+ EDX = 0x00000000;
+ }
+ break;
+
+ case 0x80000005: /*Cache information*/
+ EBX = 0x08800880; /*TLBs*/
+ ECX = 0x40040120; /*L1 data cache*/
+ EDX = 0x40020120; /*L1 instruction cache*/
+ break;
+
+ case 0x80000006: /*L2 Cache information*/
+ if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpuid_model >= 0x670)
+ ECX = 0x40040120; /*L2 cache*/
+ else
+ ECX = 0;
+ EAX = EBX = EDX = 0;
+ break;
+
+ default:
+ EAX = EBX = ECX = EDX = 0;
+ break;
+ }
+ break;
}
}
@@ -1460,6 +1802,7 @@ void cpu_RDMSR()
{
case CPU_WINCHIP:
case CPU_WINCHIP2:
+ case CPU_CYRIX_III:
EAX = EDX = 0;
switch (ECX)
{
@@ -1526,6 +1869,32 @@ void cpu_RDMSR()
break;
}
break;
+ case CPU_PENTIUMPRO:
+ case CPU_PENTIUM_2:
+ case CPU_CELERON:
+ case CPU_CELERON_A:
+ EAX = EDX = 0;
+ switch (ECX)
+ {
+ case 0x10:
+ EAX = tsc & 0xffffffff;
+ EDX = tsc >> 32;
+ break;
+
+ case 0x174:
+ EAX = sysenter_cs;
+ EDX = 0;
+ break;
+ case 0x175:
+ EAX = sysenter_esp;
+ EDX = 0;
+ break;
+ case 0x176:
+ EAX = sysenter_eip;
+ EDX = 0;
+ break;
+ }
+ break;
}
}
@@ -1535,6 +1904,7 @@ void cpu_WRMSR()
{
case CPU_WINCHIP:
case CPU_WINCHIP2:
+ case CPU_CYRIX_III:
switch (ECX)
{
case 0x02:
@@ -1609,11 +1979,39 @@ void cpu_WRMSR()
break;
}
break;
+ case CPU_PENTIUMPRO:
+ case CPU_PENTIUM_2:
+ case CPU_CELERON:
+ case CPU_CELERON_A:
+ switch (ECX)
+ {
+ case 0x10:
+ tsc = EAX | ((uint64_t)EDX << 32);
+ break;
+
+ case 0x174:
+ sysenter_cs = EAX & 0xffff;
+ break;
+ case 0x175:
+ sysenter_esp = EAX;
+ break;
+ case 0x176:
+ sysenter_eip = EAX;
+ break;
+ }
+ break;
}
}
static int cyrix_addr;
+#define CCR1_USE_SMI (1 << 1)
+#define CCR1_SMAC (1 << 2)
+#define CCR1_SM3 (1 << 7)
+
+#define CCR3_SMI_LOCK (1 << 0)
+#define CCR3_NMI_EN (1 << 1)
+
void cyrix_write(uint16_t addr, uint8_t val, void *priv)
{
if (!(addr & 1))
@@ -1624,14 +2022,46 @@ void cyrix_write(uint16_t addr, uint8_t val, void *priv)
ccr0 = val;
break;
case 0xc1: /*CCR1*/
+ if ((ccr3 & CCR3_SMI_LOCK) && !(cpu_cur_status & CPU_STATUS_SMM))
+ val = (val & ~(CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) | (ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3));
ccr1 = val;
break;
case 0xc2: /*CCR2*/
ccr2 = val;
break;
case 0xc3: /*CCR3*/
+ if ((ccr3 & CCR3_SMI_LOCK) && !(cpu_cur_status & CPU_STATUS_SMM))
+ val = (val & ~(CCR3_NMI_EN)) | (ccr3 & CCR3_NMI_EN) | CCR3_SMI_LOCK;
ccr3 = val;
break;
+ case 0xcd:
+ if (!(ccr3 & CCR3_SMI_LOCK) || (cpu_cur_status & CPU_STATUS_SMM))
+ {
+ cyrix.arr[3].base = (cyrix.arr[3].base & ~0xff000000) | (val << 24);
+ cyrix.smhr &= ~SMHR_VALID;
+ }
+ break;
+ case 0xce:
+ if (!(ccr3 & CCR3_SMI_LOCK) || (cpu_cur_status & CPU_STATUS_SMM))
+ {
+ cyrix.arr[3].base = (cyrix.arr[3].base & ~0x00ff0000) | (val << 16);
+ cyrix.smhr &= ~SMHR_VALID;
+ }
+ break;
+ case 0xcf:
+ if (!(ccr3 & CCR3_SMI_LOCK) || (cpu_cur_status & CPU_STATUS_SMM))
+ {
+ cyrix.arr[3].base = (cyrix.arr[3].base & ~0x0000f000) | ((val & 0xf0) << 8);
+ if ((val & 0xf) == 0xf)
+ cyrix.arr[3].size = 1ull << 32; /*4 GB*/
+ else if (val & 0xf)
+ cyrix.arr[3].size = 2048 << (val & 0xf);
+ else
+ cyrix.arr[3].size = 0; /*Disabled*/
+ cyrix.smhr &= ~SMHR_VALID;
+ }
+ break;
+
case 0xe8: /*CCR4*/
if ((ccr3 & 0xf0) == 0x10)
{
@@ -1672,7 +2102,6 @@ uint8_t cyrix_read(uint16_t addr, void *priv)
case 0xfe: return models[model].cpu[cpu_manufacturer].cpus[cpu].cyrix_id & 0xff;
case 0xff: return models[model].cpu[cpu_manufacturer].cpus[cpu].cyrix_id >> 8;
}
- if ((cyrix_addr & ~0xf0) == 0xc0) return 0xff;
if (cyrix_addr == 0x20 && models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_Cx5x86) return 0xff;
}
return 0xff;
@@ -1753,9 +2182,25 @@ void cpu_set_turbo(int turbo)
}
}
+int cpu_get_turbo()
+{
+ return cpu_turbo;
+}
+
int cpu_get_speed()
{
if (cpu_turbo)
return cpu_turbo_speed;
return cpu_nonturbo_speed;
}
+
+void cpu_set_nonturbo_divider(int divider)
+{
+ if (divider < 2)
+ cpu_set_turbo(1);
+ else
+ {
+ cpu_nonturbo_speed = cpu_turbo_speed / divider;
+ cpu_set_turbo(0);
+ }
+}
diff --git a/src/cpu.h b/src/cpu.h
index 2e8cc4f..97acec1 100644
--- a/src/cpu.h
+++ b/src/cpu.h
@@ -2,6 +2,7 @@
#define _CPU_H_
extern int cpu, cpu_manufacturer;
+extern int fpu_type;
/*808x class CPUs*/
#define CPU_8088 0
@@ -40,11 +41,17 @@ extern int cpu, cpu_manufacturer;
#define CPU_K6_3 25
#define CPU_K6_2P 26
#define CPU_K6_3P 27
+#define CPU_PENTIUMPRO 28
+#define CPU_PENTIUM_2 29
+#define CPU_CELERON 30
+#define CPU_CELERON_A 31
+#define CPU_CYRIX_III 32
#define MANU_INTEL 0
#define MANU_AMD 1
#define MANU_CYRIX 2
#define MANU_IDT 3
+#define MANU_VIA 4
extern int timing_rr;
extern int timing_mr, timing_mrl;
@@ -60,10 +67,28 @@ extern int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate;
extern int timing_misaligned;
+enum
+{
+ FPU_NONE,
+ FPU_8087,
+ FPU_287,
+ FPU_287XL,
+ FPU_387,
+ FPU_BUILTIN
+};
+
+typedef struct
+{
+ const char *name;
+ const char *internal_name;
+ const int type;
+} FPU;
+
typedef struct
{
char name[32];
int cpu_type;
+ const FPU *fpus;
int speed;
int rspeed;
int multi;
@@ -77,6 +102,8 @@ typedef struct
int atclk_div;
} CPU;
+extern CPU *cpu_s;
+
extern CPU cpus_8088[];
extern CPU cpus_8086[];
extern CPU cpus_286[];
@@ -95,12 +122,17 @@ extern CPU cpus_Pentium5V[];
extern CPU cpus_PentiumS5[];
extern CPU cpus_Pentium[];
extern CPU cpus_6x86[];
+extern CPU cpus_6x86_SS7[];
extern CPU cpus_K6_S7[];
extern CPU cpus_K6_SS7[];
+extern CPU cpus_PentiumPro[];
+extern CPU cpus_Slot1_100MHz[];
+extern CPU cpus_VIA_100MHz[];
extern CPU cpus_pcjr[];
extern CPU cpus_europc[];
extern CPU cpus_pc1512[];
+extern CPU cpus_super286tr[];
extern CPU cpus_ibmat[];
extern CPU cpus_ibmxt286[];
extern CPU cpus_ps1_m2011[];
@@ -114,13 +146,14 @@ extern int cpu_multi;
/*Cyrix 5x86/6x86 only has data misalignment penalties when crossing 8-byte boundaries*/
extern int cpu_cyrix_alignment;
-#define CPU_FEATURE_RDTSC (1 << 0)
-#define CPU_FEATURE_MSR (1 << 1)
-#define CPU_FEATURE_MMX (1 << 2)
-#define CPU_FEATURE_CR4 (1 << 3)
-#define CPU_FEATURE_VME (1 << 4)
-#define CPU_FEATURE_CX8 (1 << 5)
-#define CPU_FEATURE_3DNOW (1 << 6)
+#define CPU_FEATURE_RDTSC (1 << 0)
+#define CPU_FEATURE_MSR (1 << 1)
+#define CPU_FEATURE_MMX (1 << 2)
+#define CPU_FEATURE_CR4 (1 << 3)
+#define CPU_FEATURE_VME (1 << 4)
+#define CPU_FEATURE_CX8 (1 << 5)
+#define CPU_FEATURE_3DNOW (1 << 6)
+#define CPU_FEATURE_SYSCALL (1 << 7)
extern uint32_t cpu_features;
static inline int cpu_has_feature(int feature)
@@ -163,12 +196,20 @@ extern uint64_t xt_cpu_multi;
extern int isa_cycles;
#define ISA_CYCLES(x) (x * isa_cycles)
+#define CPU_CLOCK_DIVIDER_MAX 16384
void cpu_update_waitstates();
void cpu_set();
void cpu_set_edx();
void cpu_set_turbo(int turbo);
+int cpu_get_turbo();
+void cpu_set_nonturbo_divider(int divider);
int cpu_get_speed();
extern int has_vlb;
+int fpu_get_type(int model, int manu, int cpu, const char *internal_name);
+const char *fpu_get_internal_name(int model, int manu, int cpu, int type);
+const char *fpu_get_name_from_index(int model, int manu, int cpu, int c);
+int fpu_get_type_from_index(int model, int manu, int cpu, int c);
+
#endif
diff --git a/src/cpu_tables.c b/src/cpu_tables.c
index ea5e2d1..c0bd920 100644
--- a/src/cpu_tables.c
+++ b/src/cpu_tables.c
@@ -22,409 +22,530 @@
17 = 200 MHz
*/
+FPU fpus_none[] =
+{
+ {"None", "none", FPU_NONE},
+ {NULL, NULL, 0}
+};
+FPU fpus_8088[] =
+{
+ {"None", "none", FPU_NONE},
+ {"8087", "8087", FPU_8087},
+ {NULL, NULL, 0}
+};
+FPU fpus_80286[] =
+{
+ {"None", "none", FPU_NONE},
+ {"287", "287", FPU_287},
+ {"287XL", "287xl", FPU_287XL},
+ {NULL, NULL, 0}
+};
+FPU fpus_80386[] =
+{
+ {"None", "none", FPU_NONE},
+ {"387", "387", FPU_387},
+ {NULL, NULL, 0}
+};
+FPU fpus_builtin[] =
+{
+ {"Built-in", "builtin", FPU_BUILTIN},
+ {NULL, NULL, 0}
+};
+
CPU cpus_8088[] =
{
/*8088 standard*/
- {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8088/8", CPU_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8088/10", CPU_8088, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8088/12", CPU_8088, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8088/16", CPU_8088, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8088/4.77", CPU_8088, fpus_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8088/7.16", CPU_8088, fpus_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8088/8", CPU_8088, fpus_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8088/10", CPU_8088, fpus_8088, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8088/12", CPU_8088, fpus_8088, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8088/16", CPU_8088, fpus_8088, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"", -1, 0, 0, 0, 0}
};
CPU cpus_pcjr[] =
{
/*8088 PCjr*/
- {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8088/4.77", CPU_8088, fpus_none, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"", -1, 0, 0, 0, 0}
};
CPU cpus_europc[] =
{
/*8088 EuroPC*/
- {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8088/9.54", CPU_8088, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8088/4.77", CPU_8088, fpus_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8088/7.16", CPU_8088, fpus_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8088/9.54", CPU_8088, fpus_8088, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"", -1, 0, 0, 0, 0}
};
CPU cpus_8086[] =
{
/*8086 standard*/
- {"8086/7.16", CPU_8086, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8086/9.54", CPU_8086, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8086/10", CPU_8086, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8086/12", CPU_8086, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8086/16", CPU_8086, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2},
+ {"8086/7.16", CPU_8086, fpus_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8086/8", CPU_8086, fpus_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8086/9.54", CPU_8086, fpus_8088, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8086/10", CPU_8086, fpus_8088, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8086/12", CPU_8086, fpus_8088, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8086/16", CPU_8086, fpus_8088, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2},
{"", -1, 0, 0, 0, 0}
};
CPU cpus_pc1512[] =
{
/*8086 Amstrad*/
- {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
+ {"8086/8", CPU_8086, fpus_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"", -1, 0, 0, 0, 0}
};
CPU cpus_286[] =
{
/*286*/
- {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
- {"286/8", CPU_286, 1, 8000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
- {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
- {"286/12", CPU_286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
- {"286/16", CPU_286, 4, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
- {"286/20", CPU_286, 5, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
- {"286/25", CPU_286, 6, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
+ {"286/6", CPU_286, fpus_80286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
+ {"286/8", CPU_286, fpus_80286, 1, 8000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
+ {"286/10", CPU_286, fpus_80286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
+ {"286/12", CPU_286, fpus_80286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
+ {"286/16", CPU_286, fpus_80286, 4, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
+ {"286/20", CPU_286, fpus_80286, 5, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
+ {"286/25", CPU_286, fpus_80286, 6, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
+ {"", -1, 0, 0, 0, 0}
+};
+
+CPU cpus_super286tr[] =
+{
+ /*286*/
+ {"286/12", CPU_286, fpus_80286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
{"", -1, 0, 0, 0, 0}
};
CPU cpus_ibmat[] =
{
/*286*/
- {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1},
- {"286/8", CPU_286, 0, 8000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1},
+ {"286/6", CPU_286, fpus_80286, 0, 6000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1},
+ {"286/8", CPU_286, fpus_80286, 0, 8000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1},
{"", -1, 0, 0, 0, 0}
};
CPU cpus_ibmxt286[] =
{
/*286*/
- {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
+ {"286/6", CPU_286, fpus_80286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
{"", -1, 0, 0, 0, 0}
};
CPU cpus_ps1_m2011[] =
{
/*286*/
- {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
+ {"286/10", CPU_286, fpus_80286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
{"", -1, 0, 0, 0, 0}
};
CPU cpus_ps2_m30_286[] =
{
/*286*/
- {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
- {"286/12", CPU_286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
- {"286/16", CPU_286, 4, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
- {"286/20", CPU_286, 5, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
- {"286/25", CPU_286, 6, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
+ {"286/10", CPU_286, fpus_80286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
+ {"286/12", CPU_286, fpus_80286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
+ {"286/16", CPU_286, fpus_80286, 4, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
+ {"286/20", CPU_286, fpus_80286, 5, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
+ {"286/25", CPU_286, fpus_80286, 6, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
{"", -1, 0, 0, 0, 0}
};
CPU cpus_i386SX[] =
{
/*i386SX*/
- {"i386SX/16", CPU_386SX, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2},
- {"i386SX/20", CPU_386SX, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
- {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
- {"i386SX/33", CPU_386SX, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4},
+ {"i386SX/16", CPU_386SX, fpus_80386, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2},
+ {"i386SX/20", CPU_386SX, fpus_80386, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
+ {"i386SX/25", CPU_386SX, fpus_80386, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
+ {"i386SX/33", CPU_386SX, fpus_80386, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4},
{"", -1, 0, 0, 0}
};
CPU cpus_i386DX[] =
{
/*i386DX*/
- {"i386DX/16", CPU_386DX, 0, 16000000, 1, 0, 0x0308, 0, 0, 0, 3,3,3,3, 2},
- {"i386DX/20", CPU_386DX, 1, 20000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
- {"i386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
- {"i386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4},
+ {"i386DX/16", CPU_386DX, fpus_80386, 0, 16000000, 1, 0, 0x0308, 0, 0, 0, 3,3,3,3, 2},
+ {"i386DX/20", CPU_386DX, fpus_80386, 1, 20000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
+ {"i386DX/25", CPU_386DX, fpus_80386, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
+ {"i386DX/33", CPU_386DX, fpus_80386, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4},
{"", -1, 0, 0, 0}
};
CPU cpus_acer[] =
{
/*i386SX*/
- {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,4,4, 3},
+ {"i386SX/25", CPU_386SX, fpus_80386, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,4,4, 3},
{"", -1, 0, 0, 0}
};
CPU cpus_Am386SX[] =
{
/*Am386*/
- {"Am386SX/16", CPU_386SX, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2},
- {"Am386SX/20", CPU_386SX, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
- {"Am386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
- {"Am386SX/33", CPU_386SX, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4},
- {"Am386SX/40", CPU_386SX, 4, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3, 5},
+ {"Am386SX/16", CPU_386SX, fpus_80386, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2},
+ {"Am386SX/20", CPU_386SX, fpus_80386, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
+ {"Am386SX/25", CPU_386SX, fpus_80386, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
+ {"Am386SX/33", CPU_386SX, fpus_80386, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4},
+ {"Am386SX/40", CPU_386SX, fpus_80386, 4, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3, 5},
{"", -1, 0, 0, 0}
};
CPU cpus_Am386DX[] =
{
/*Am386*/
- {"Am386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
- {"Am386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4},
- {"Am386DX/40", CPU_386DX, 4, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5},
+ {"Am386DX/25", CPU_386DX, fpus_80386, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
+ {"Am386DX/33", CPU_386DX, fpus_80386, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4},
+ {"Am386DX/40", CPU_386DX, fpus_80386, 4, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5},
{"", -1, 0, 0, 0}
};
CPU cpus_486SLC[] =
{
/*Cx486SLC*/
- {"Cx486SLC/20", CPU_486SLC, 1, 20000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3},
- {"Cx486SLC/25", CPU_486SLC, 2, 25000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3},
- {"Cx486SLC/33", CPU_486SLC, 3, 33333333, 1, 0, 0x400, 0, 0x0000, 0, 6,6,3,3, 4},
- {"Cx486SRx2/32", CPU_486SLC, 3, 32000000, 2, 0, 0x406, 0, 0x0006, 0, 6,6,6,6, 2*2},
- {"Cx486SRx2/40", CPU_486SLC, 4, 40000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 2*3},
- {"Cx486SRx2/50", CPU_486SLC, 5, 50000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 2*3},
+ {"Cx486SLC/20", CPU_486SLC, fpus_80386, 1, 20000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3},
+ {"Cx486SLC/25", CPU_486SLC, fpus_80386, 2, 25000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3},
+ {"Cx486SLC/33", CPU_486SLC, fpus_80386, 3, 33333333, 1, 0, 0x400, 0, 0x0000, 0, 6,6,3,3, 4},
+ {"Cx486SRx2/32", CPU_486SLC, fpus_80386, 3, 32000000, 2, 0, 0x406, 0, 0x0006, 0, 6,6,6,6, 2*2},
+ {"Cx486SRx2/40", CPU_486SLC, fpus_80386, 4, 40000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 2*3},
+ {"Cx486SRx2/50", CPU_486SLC, fpus_80386, 5, 50000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 2*3},
{"", -1, 0, 0, 0}
};
CPU cpus_486DLC[] =
{
/*Cx486DLC*/
- {"Cx486DLC/25", CPU_486DLC, 2, 25000000, 1, 0, 0x401, 0, 0x0001, 0, 4,4,3,3, 3},
- {"Cx486DLC/33", CPU_486DLC, 3, 33333333, 1, 0, 0x401, 0, 0x0001, 0, 6,6,3,3, 4},
- {"Cx486DLC/40", CPU_486DLC, 4, 40000000, 1, 0, 0x401, 0, 0x0001, 0, 7,7,3,3, 5},
- {"Cx486DRx2/32", CPU_486DLC, 3, 32000000, 2, 0, 0x407, 0, 0x0007, 0, 6,6,6,6, 2*2},
- {"Cx486DRx2/40", CPU_486DLC, 4, 40000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6, 2*3},
- {"Cx486DRx2/50", CPU_486DLC, 5, 50000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6, 2*3},
- {"Cx486DRx2/66", CPU_486DLC, 6, 66666666, 2, 0, 0x407, 0, 0x0007, 0, 12,12,6,6, 2*4},
+ {"Cx486DLC/25", CPU_486DLC, fpus_80386, 2, 25000000, 1, 0, 0x401, 0, 0x0001, 0, 4,4,3,3, 3},
+ {"Cx486DLC/33", CPU_486DLC, fpus_80386, 3, 33333333, 1, 0, 0x401, 0, 0x0001, 0, 6,6,3,3, 4},
+ {"Cx486DLC/40", CPU_486DLC, fpus_80386, 4, 40000000, 1, 0, 0x401, 0, 0x0001, 0, 7,7,3,3, 5},
+ {"Cx486DRx2/32", CPU_486DLC, fpus_80386, 3, 32000000, 2, 0, 0x407, 0, 0x0007, 0, 6,6,6,6, 2*2},
+ {"Cx486DRx2/40", CPU_486DLC, fpus_80386, 4, 40000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6, 2*3},
+ {"Cx486DRx2/50", CPU_486DLC, fpus_80386, 5, 50000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6, 2*3},
+ {"Cx486DRx2/66", CPU_486DLC, fpus_80386, 6, 66666666, 2, 0, 0x407, 0, 0x0007, 0, 12,12,6,6, 2*4},
{"", -1, 0, 0, 0}
};
CPU cpus_i486[] =
{
/*i486*/
- {"i486SX/16", CPU_i486SX, 0, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3,3,3,3, 2},
- {"i486SX/20", CPU_i486SX, 1, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
- {"i486SX/25", CPU_i486SX, 2, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
- {"i486SX/33", CPU_i486SX, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
- {"i486SX2/50", CPU_i486SX, 5, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
- {"i486DX/25", CPU_i486DX, 2, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
- {"i486DX/33", CPU_i486DX, 3, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
- {"i486DX/50", CPU_i486DX, 5, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4, 6},
- {"i486DX2/40", CPU_i486DX, 4, 40000000, 2, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
- {"i486DX2/50", CPU_i486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
- {"i486DX2/66", CPU_i486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4},
- {"iDX4/75", CPU_iDX4, 7, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3}, /*CPUID available on DX4, >= 75 MHz*/
- {"iDX4/100", CPU_iDX4, 10, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*4}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/
- {"Pentium OverDrive/63", CPU_PENTIUM, 6, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, (5*3)/2},
- {"Pentium OverDrive/83", CPU_PENTIUM, 8, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, (5*4)/2},
+ {"i486SX/16", CPU_i486SX, fpus_none, 0, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3,3,3,3, 2},
+ {"i486SX/20", CPU_i486SX, fpus_none, 1, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
+ {"i486SX/25", CPU_i486SX, fpus_none, 2, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
+ {"i486SX/33", CPU_i486SX, fpus_none, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
+ {"i486SX2/50", CPU_i486SX, fpus_none, 5, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
+ {"i486DX/25", CPU_i486DX, fpus_builtin, 2, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
+ {"i486DX/33", CPU_i486DX, fpus_builtin, 3, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
+ {"i486DX/50", CPU_i486DX, fpus_builtin, 5, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4, 6},
+ {"i486DX2/40", CPU_i486DX, fpus_builtin, 4, 40000000, 2, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
+ {"i486DX2/50", CPU_i486DX, fpus_builtin, 5, 50000000, 2, 25000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
+ {"i486DX2/66", CPU_i486DX, fpus_builtin, 6, 66666666, 2, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4},
+ {"iDX4/75", CPU_iDX4, fpus_builtin, 7, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3}, /*CPUID available on DX4, >= 75 MHz*/
+ {"iDX4/100", CPU_iDX4, fpus_builtin, 10, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*4}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/
+ {"Pentium OverDrive/63", CPU_PENTIUM, fpus_builtin, 6, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, (5*3)/2},
+ {"Pentium OverDrive/83", CPU_PENTIUM, fpus_builtin, 8, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, (5*4)/2},
{"", -1, 0, 0, 0}
};
CPU cpus_Am486[] =
{
/*Am486/5x86*/
- {"Am486SX/33", CPU_Am486SX, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
- {"Am486SX/40", CPU_Am486SX, 4, 40000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
- {"Am486SX2/50", CPU_Am486SX, 5, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/
- {"Am486SX2/66", CPU_Am486SX, 6, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4}, /*Isn't on all real AMD SX2s and DX2s, availability here is pretty arbitary (and distinguishes them from the Intel chips)*/
- {"Am486DX/33", CPU_Am486DX, 3, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
- {"Am486DX/40", CPU_Am486DX, 4, 40000000, 1, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
- {"Am486DX2/50", CPU_Am486DX, 5, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
- {"Am486DX2/66", CPU_Am486DX, 6, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4},
- {"Am486DX2/80", CPU_Am486DX, 8, 80000000, 2, 20000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14,6,6, 2*5},
- {"Am486DX4/75", CPU_Am486DX, 7, 75000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3},
- {"Am486DX4/90", CPU_Am486DX, 9, 90000000, 3, 30000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4},
- {"Am486DX4/100", CPU_Am486DX, 10, 100000000, 3, 33333333, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4},
- {"Am486DX4/120", CPU_Am486DX, 11, 120000000, 3, 20000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21,9,9, 3*5},
- {"Am5x86/P75", CPU_Am486DX, 12, 133333333, 4, 33333333, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*4},
- {"Am5x86/P75+", CPU_Am486DX, 13, 160000000, 4, 20000000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 4*5},
+ {"Am486SX/33", CPU_Am486SX, fpus_none, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
+ {"Am486SX/40", CPU_Am486SX, fpus_none, 4, 40000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
+ {"Am486SX2/50", CPU_Am486SX, fpus_none, 5, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/
+ {"Am486SX2/66", CPU_Am486SX, fpus_none, 6, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4}, /*Isn't on all real AMD SX2s and DX2s, availability here is pretty arbitary (and distinguishes them from the Intel chips)*/
+ {"Am486DX/33", CPU_Am486DX, fpus_builtin, 3, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
+ {"Am486DX/40", CPU_Am486DX, fpus_builtin, 4, 40000000, 1, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
+ {"Am486DX2/50", CPU_Am486DX, fpus_builtin, 5, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
+ {"Am486DX2/66", CPU_Am486DX, fpus_builtin, 6, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4},
+ {"Am486DX2/80", CPU_Am486DX, fpus_builtin, 8, 80000000, 2, 20000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14,6,6, 2*5},
+ {"Am486DX4/75", CPU_Am486DX, fpus_builtin, 7, 75000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3},
+ {"Am486DX4/90", CPU_Am486DX, fpus_builtin, 9, 90000000, 3, 30000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4},
+ {"Am486DX4/100", CPU_Am486DX, fpus_builtin, 10, 100000000, 3, 33333333, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4},
+ {"Am486DX4/120", CPU_Am486DX, fpus_builtin, 11, 120000000, 3, 20000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21,9,9, 3*5},
+ {"Am5x86/P75", CPU_Am486DX, fpus_builtin, 12, 133333333, 4, 33333333, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*4},
+ {"Am5x86/P75+", CPU_Am486DX, fpus_builtin, 13, 160000000, 4, 20000000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 4*5},
{"", -1, 0, 0, 0}
};
CPU cpus_Cx486[] =
{
/*Cx486/5x86*/
- {"Cx486S/25", CPU_Cx486S, 2, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
- {"Cx486S/33", CPU_Cx486S, 3, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
- {"Cx486S/40", CPU_Cx486S, 4, 40000000, 1, 20000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
- {"Cx486DX/33", CPU_Cx486DX, 3, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
- {"Cx486DX/40", CPU_Cx486DX, 4, 40000000, 1, 20000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
- {"Cx486DX2/50", CPU_Cx486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
- {"Cx486DX2/66", CPU_Cx486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4},
- {"Cx486DX2/80", CPU_Cx486DX, 8, 80000000, 2, 20000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14,16,16, 2*5},
- {"Cx486DX4/75", CPU_Cx486DX, 7, 75000000, 3, 25000000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3},
- {"Cx486DX4/100", CPU_Cx486DX, 10, 100000000, 3, 33333333, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4},
- {"Cx5x86/100", CPU_Cx5x86, 10, 100000000, 3, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4},
- {"Cx5x86/120", CPU_Cx5x86, 11, 120000000, 3, 20000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21,9,9, 3*5},
- {"Cx5x86/133", CPU_Cx5x86, 12, 133333333, 4, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*4},
+ {"Cx486S/25", CPU_Cx486S, fpus_none, 2, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
+ {"Cx486S/33", CPU_Cx486S, fpus_none, 3, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
+ {"Cx486S/40", CPU_Cx486S, fpus_none, 4, 40000000, 1, 20000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
+ {"Cx486DX/33", CPU_Cx486DX, fpus_builtin, 3, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
+ {"Cx486DX/40", CPU_Cx486DX, fpus_builtin, 4, 40000000, 1, 20000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
+ {"Cx486DX2/50", CPU_Cx486DX, fpus_builtin, 5, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
+ {"Cx486DX2/66", CPU_Cx486DX, fpus_builtin, 6, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4},
+ {"Cx486DX2/80", CPU_Cx486DX, fpus_builtin, 8, 80000000, 2, 20000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14,16,16, 2*5},
+ {"Cx486DX4/75", CPU_Cx486DX, fpus_builtin, 7, 75000000, 3, 25000000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3},
+ {"Cx486DX4/100", CPU_Cx486DX, fpus_builtin, 10, 100000000, 3, 33333333, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4},
+ {"Cx5x86/100", CPU_Cx5x86, fpus_builtin, 10, 100000000, 3, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4},
+ {"Cx5x86/120", CPU_Cx5x86, fpus_builtin, 11, 120000000, 3, 20000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21,9,9, 3*5},
+ {"Cx5x86/133", CPU_Cx5x86, fpus_builtin, 12, 133333333, 4, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*4},
{"", -1, 0, 0, 0}
};
- CPU cpus_6x86[] =
- {
- /*Cyrix 6x86*/
- {"6x86-P90", CPU_Cx6x86, 17, 80000000, 3, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8,8,6,6, 2*5},
- {"6x86-PR120+", CPU_Cx6x86, 17, 100000000, 3, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6},
- {"6x86-PR133+", CPU_Cx6x86, 17, 110000000, 3, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*7},
- {"6x86-PR150+", CPU_Cx6x86, 17, 120000000, 3, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
- {"6x86-PR166+", CPU_Cx6x86, 17, 133333333, 3, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
- {"6x86-PR200+", CPU_Cx6x86, 17, 150000000, 3, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*9},
+CPU cpus_6x86[] =
+{
+ /*Cyrix 6x86*/
+ {"6x86-P90", CPU_Cx6x86, fpus_builtin, 17, 80000000, 3, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8,8,6,6, 2*5},
+ {"6x86-PR120+", CPU_Cx6x86, fpus_builtin, 17, 100000000, 3, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6},
+ {"6x86-PR133+", CPU_Cx6x86, fpus_builtin, 17, 110000000, 3, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*7},
+ {"6x86-PR150+", CPU_Cx6x86, fpus_builtin, 17, 120000000, 3, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
+ {"6x86-PR166+", CPU_Cx6x86, fpus_builtin, 17, 133333333, 3, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
+ {"6x86-PR200+", CPU_Cx6x86, fpus_builtin, 17, 150000000, 3, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*9},
- /*Cyrix 6x86L*/
- {"6x86L-PR133+", CPU_Cx6x86L, 19, 110000000, 3, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*7},
- {"6x86L-PR150+", CPU_Cx6x86L, 19, 120000000, 3, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
- {"6x86L-PR166+", CPU_Cx6x86L, 19, 133333333, 3, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
- {"6x86L-PR200+", CPU_Cx6x86L, 19, 150000000, 3, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*9},
+ /*Cyrix 6x86L*/
+ {"6x86L-PR133+", CPU_Cx6x86L, fpus_builtin, 19, 110000000, 3, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*7},
+ {"6x86L-PR150+", CPU_Cx6x86L, fpus_builtin, 19, 120000000, 3, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
+ {"6x86L-PR166+", CPU_Cx6x86L, fpus_builtin, 19, 133333333, 3, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
+ {"6x86L-PR200+", CPU_Cx6x86L, fpus_builtin, 19, 150000000, 3, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*9},
- /*Cyrix 6x86MX*/
- {"6x86MX-PR166", CPU_Cx6x86MX, 18, 133333333, 3, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
- {"6x86MX-PR200", CPU_Cx6x86MX, 18, 166666666, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"6x86MX-PR233", CPU_Cx6x86MX, 18, 188888888, 3, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*9)/2},
- {"6x86MX-PR266", CPU_Cx6x86MX, 18, 207500000, 3, 41666667, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17,7,7, (5*10)/2},
- {"6x86MX-PR300", CPU_Cx6x86MX, 18, 233333333, 3, 33333333, 0x600, 0x600, 0x0454, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,7,7, (7*8)/2},
- {"6x86MX-PR333", CPU_Cx6x86MX, 18, 250000000, 3, 41666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20,9,9, 3*10},
- {"6x86MX-PR366", CPU_Cx6x86MX, 18, 250000000, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 3*10},
- {"6x86MX-PR400", CPU_Cx6x86MX, 18, 285000000, 3, 31666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*11},
- {"", -1, 0, 0, 0}
- };
+ /*Cyrix 6x86MX*/
+ {"6x86MX-PR166", CPU_Cx6x86MX, fpus_builtin, 18, 133333333, 3, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
+ {"6x86MX-PR200", CPU_Cx6x86MX, fpus_builtin, 18, 166666666, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
+ {"6x86MX-PR233", CPU_Cx6x86MX, fpus_builtin, 18, 188888888, 3, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*9)/2},
+ {"6x86MX-PR266", CPU_Cx6x86MX, fpus_builtin, 18, 207500000, 3, 41666667, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17,7,7, (5*10)/2},
+ /*Cyrix M II*/
+ {"M II-200", CPU_Cx6x86MX, fpus_builtin, 18, 166666666, 3, 33333333, 0x600, 0x600, 0x0854, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
+ {"M II-233", CPU_Cx6x86MX, fpus_builtin, 18, 188888888, 3, 37500000, 0x601, 0x601, 0x0854, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*9)/2},
+ {"M II-266", CPU_Cx6x86MX, fpus_builtin, 18, 207500000, 3, 41666667, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17,7,7, (5*10)/2},
+ {"M II-300", CPU_Cx6x86MX, fpus_builtin, 18, 233333333, 3, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,7,7, (7*8)/2},
+ {"M II-333", CPU_Cx6x86MX, fpus_builtin, 18, 250000000, 3, 41666667, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20,9,9, 3*10},
+ {"", -1, 0, 0, 0}
+};
+
+CPU cpus_6x86_SS7[] =
+{
+ /*Cyrix 6x86*/
+ {"6x86-P90", CPU_Cx6x86, fpus_builtin, 17, 80000000, 3, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8,8,6,6, 2*5},
+ {"6x86-PR120+", CPU_Cx6x86, fpus_builtin, 17, 100000000, 3, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6},
+ {"6x86-PR133+", CPU_Cx6x86, fpus_builtin, 17, 110000000, 3, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*7},
+ {"6x86-PR150+", CPU_Cx6x86, fpus_builtin, 17, 120000000, 3, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
+ {"6x86-PR166+", CPU_Cx6x86, fpus_builtin, 17, 133333333, 3, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
+ {"6x86-PR200+", CPU_Cx6x86, fpus_builtin, 17, 150000000, 3, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*9},
+
+ /*Cyrix 6x86L*/
+ {"6x86L-PR133+", CPU_Cx6x86L, fpus_builtin, 19, 110000000, 3, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*7},
+ {"6x86L-PR150+", CPU_Cx6x86L, fpus_builtin, 19, 120000000, 3, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
+ {"6x86L-PR166+", CPU_Cx6x86L, fpus_builtin, 19, 133333333, 3, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
+ {"6x86L-PR200+", CPU_Cx6x86L, fpus_builtin, 19, 150000000, 3, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*9},
+
+ /*Cyrix 6x86MX*/
+ {"6x86MX-PR166", CPU_Cx6x86MX, fpus_builtin, 18, 133333333, 3, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
+ {"6x86MX-PR200", CPU_Cx6x86MX, fpus_builtin, 18, 166666666, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
+ {"6x86MX-PR233", CPU_Cx6x86MX, fpus_builtin, 18, 188888888, 3, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*9)/2},
+ {"6x86MX-PR266", CPU_Cx6x86MX, fpus_builtin, 18, 207500000, 3, 41666667, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17,7,7, (5*10)/2},
+
+ /*Cyrix M II*/
+ {"M II-200", CPU_Cx6x86MX, fpus_builtin, 18, 166666666, 3, 33333333, 0x600, 0x600, 0x0854, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
+ {"M II-233", CPU_Cx6x86MX, fpus_builtin, 18, 188888888, 3, 37500000, 0x601, 0x601, 0x0854, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*9)/2},
+ {"M II-266", CPU_Cx6x86MX, fpus_builtin, 18, 207500000, 3, 41666667, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17,7,7, (5*10)/2},
+ {"M II-300", CPU_Cx6x86MX, fpus_builtin, 18, 233333333, 3, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,7,7, (7*8)/2},
+ {"M II-333", CPU_Cx6x86MX, fpus_builtin, 18, 250000000, 3, 41666667, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20,9,9, 3*10},
+ {"M II-366", CPU_Cx6x86MX, fpus_builtin, 18, 250000000, 3, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 3*10},
+ {"M II-400", CPU_Cx6x86MX, fpus_builtin, 18, 285000000, 3, 31666667, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*11},
+ {"M II-433", CPU_Cx6x86MX, fpus_builtin, 18, 300000000, 3, 33333333, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*12},
+ {"", -1, 0, 0, 0}
+};
CPU cpus_WinChip[] =
{
/*IDT WinChip*/
- {"WinChip 75", CPU_WINCHIP, 7, 75000000, 2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4, (3*6)/2},
- {"WinChip 90", CPU_WINCHIP, 9, 90000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4, (3*7)/2},
- {"WinChip 100", CPU_WINCHIP, 10, 100000000, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4, (3*8)/2},
- {"WinChip 120", CPU_WINCHIP, 11, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*7},
- {"WinChip 133", CPU_WINCHIP, 12, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*8},
- {"WinChip 150", CPU_WINCHIP, 13, 150000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, (5*7)/2},
- {"WinChip 166", CPU_WINCHIP, 15, 166666666, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, (5*8)/2},
- {"WinChip 180", CPU_WINCHIP, 16, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*7},
- {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
- {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7},
- {"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
- {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30},
- {"WinChip 2A/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
- {"WinChip 2A/233", CPU_WINCHIP2, 17, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, (7*8)/2},
+ {"WinChip 75", CPU_WINCHIP, fpus_builtin, 7, 75000000, 2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4, (3*6)/2},
+ {"WinChip 90", CPU_WINCHIP, fpus_builtin, 9, 90000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4, (3*7)/2},
+ {"WinChip 100", CPU_WINCHIP, fpus_builtin, 10, 100000000, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4, (3*8)/2},
+ {"WinChip 120", CPU_WINCHIP, fpus_builtin, 11, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*7},
+ {"WinChip 133", CPU_WINCHIP, fpus_builtin, 12, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*8},
+ {"WinChip 150", CPU_WINCHIP, fpus_builtin, 13, 150000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, (5*7)/2},
+ {"WinChip 166", CPU_WINCHIP, fpus_builtin, 15, 166666666, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, (5*8)/2},
+ {"WinChip 180", CPU_WINCHIP, fpus_builtin, 16, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*7},
+ {"WinChip 200", CPU_WINCHIP, fpus_builtin, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
+ {"WinChip 240", CPU_WINCHIP, fpus_builtin, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7},
+ {"WinChip 2/200", CPU_WINCHIP2, fpus_builtin, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
+ {"WinChip 2/240", CPU_WINCHIP2, fpus_builtin, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30},
+ {"WinChip 2A/200", CPU_WINCHIP2, fpus_builtin, 17, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
+ {"WinChip 2A/233", CPU_WINCHIP2, fpus_builtin, 17, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, (7*8)/2},
{"", -1, 0, 0, 0}
};
CPU cpus_WinChip_SS7[] =
{
/*IDT WinChip (Super Socket 7)*/
- {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
- {"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9},
- {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7},
- {"WinChip 2/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
- {"WinChip 2/225", CPU_WINCHIP2, 17, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9},
- {"WinChip 2/240", CPU_WINCHIP2, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30},
- {"WinChip 2/250", CPU_WINCHIP2, 17, 250000000, 6, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30},
- {"WinChip 2A/200", CPU_WINCHIP2, 17, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 24},
- {"WinChip 2A/233", CPU_WINCHIP2, 17, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 28},
- {"WinChip 2A/266", CPU_WINCHIP2, 17, 233333333, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 28},
- {"WinChip 2A/300", CPU_WINCHIP2, 17, 250000000, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30},
+ {"WinChip 200", CPU_WINCHIP, fpus_builtin, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
+ {"WinChip 225", CPU_WINCHIP, fpus_builtin, 17, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9},
+ {"WinChip 240", CPU_WINCHIP, fpus_builtin, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7},
+ {"WinChip 2/200", CPU_WINCHIP2, fpus_builtin, 17, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
+ {"WinChip 2/225", CPU_WINCHIP2, fpus_builtin, 17, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9},
+ {"WinChip 2/240", CPU_WINCHIP2, fpus_builtin, 17, 240000000, 6, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30},
+ {"WinChip 2/250", CPU_WINCHIP2, fpus_builtin, 17, 250000000, 6, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30},
+ {"WinChip 2A/200", CPU_WINCHIP2, fpus_builtin, 17, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 24},
+ {"WinChip 2A/233", CPU_WINCHIP2, fpus_builtin, 17, 233333333, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 28},
+ {"WinChip 2A/266", CPU_WINCHIP2, fpus_builtin, 17, 233333333, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 28},
+ {"WinChip 2A/300", CPU_WINCHIP2, fpus_builtin, 17, 250000000, 6, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 30},
{"", -1, 0, 0, 0}
};
CPU cpus_Pentium5V[] =
{
/*Intel Pentium (5V, socket 4)*/
- {"Pentium 60", CPU_PENTIUM, 6, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 7},
- {"Pentium 66", CPU_PENTIUM, 6, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 8},
- {"Pentium OverDrive 120",CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
- {"Pentium OverDrive 133",CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
+ {"Pentium 60", CPU_PENTIUM, fpus_builtin, 6, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 7},
+ {"Pentium 66", CPU_PENTIUM, fpus_builtin, 6, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 8},
+ {"Pentium OverDrive 120", CPU_PENTIUM, fpus_builtin, 14, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
+ {"Pentium OverDrive 133", CPU_PENTIUM, fpus_builtin, 16, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
{"", -1, 0, 0, 0}
};
CPU cpus_PentiumS5[] =
{
/*Intel Pentium (Socket 5)*/
- {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, (3*6)/2},
- {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*7)/2},
- {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6},
- {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*8)/2},
- {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
- {"Pentium 133", CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
- {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2},
- {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
- {"Pentium OverDrive 166",CPU_PENTIUM,17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX,15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2},
- {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX,17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
- {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX,19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX,20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*7},
- {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX,21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
+ {"Pentium 75", CPU_PENTIUM, fpus_builtin, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, (3*6)/2},
+ {"Pentium 90", CPU_PENTIUM, fpus_builtin, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*7)/2},
+ {"Pentium 100/50", CPU_PENTIUM, fpus_builtin, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6},
+ {"Pentium 100/66", CPU_PENTIUM, fpus_builtin, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*8)/2},
+ {"Pentium 120", CPU_PENTIUM, fpus_builtin, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
+ {"Pentium 133", CPU_PENTIUM, fpus_builtin, 16, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
+ {"Pentium OverDrive 125",CPU_PENTIUM,fpus_builtin, 15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2},
+ {"Pentium OverDrive 150",CPU_PENTIUM,fpus_builtin, 17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
+ {"Pentium OverDrive 166",CPU_PENTIUM,fpus_builtin, 17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
+ {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, fpus_builtin, 15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2},
+ {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, fpus_builtin, 17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
+ {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, fpus_builtin, 19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
+ {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, fpus_builtin, 20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*7},
+ {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, fpus_builtin, 21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
{"", -1, 0, 0, 0}
};
CPU cpus_Pentium[] =
{
/*Intel Pentium*/
- {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, (3*6)/2},
- {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*7)/2},
- {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6},
- {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*8)/2},
- {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
- {"Pentium 133", CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
- {"Pentium 150", CPU_PENTIUM, 17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
- {"Pentium 166", CPU_PENTIUM, 19, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"Pentium 200", CPU_PENTIUM, 21, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
- {"Pentium MMX 166", CPU_PENTIUMMMX, 19, 166666666, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"Pentium MMX 200", CPU_PENTIUMMMX, 21, 200000000, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
- {"Pentium MMX 233", CPU_PENTIUMMMX, 24, 233333333, 4, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, (7*8)/2},
- {"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 14, 120000000, 2, 30000000, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
- {"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 16, 133333333, 2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
- {"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 17, 150000000, 3, 30000000, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
- {"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 19, 166666666, 3, 33333333, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 21, 200000000, 3, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
- {"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 24, 233333333, 4, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, (7*8)/2},
- {"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 26, 266666666, 4, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 4*8},
- {"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 28, 300000000, 5, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, (9*8)/2},
- {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2},
- {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
- {"Pentium OverDrive 166",CPU_PENTIUM,17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX,15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2},
- {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX,17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
- {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX,19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX,20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*7},
- {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX,21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
+ {"Pentium 75", CPU_PENTIUM, fpus_builtin, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, (3*6)/2},
+ {"Pentium 90", CPU_PENTIUM, fpus_builtin, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*7)/2},
+ {"Pentium 100/50", CPU_PENTIUM, fpus_builtin, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6},
+ {"Pentium 100/66", CPU_PENTIUM, fpus_builtin, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*8)/2},
+ {"Pentium 120", CPU_PENTIUM, fpus_builtin, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
+ {"Pentium 133", CPU_PENTIUM, fpus_builtin, 16, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
+ {"Pentium 150", CPU_PENTIUM, fpus_builtin, 17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
+ {"Pentium 166", CPU_PENTIUM, fpus_builtin, 19, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
+ {"Pentium 200", CPU_PENTIUM, fpus_builtin, 21, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
+ {"Pentium MMX 166", CPU_PENTIUMMMX, fpus_builtin, 19, 166666666, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
+ {"Pentium MMX 200", CPU_PENTIUMMMX, fpus_builtin, 21, 200000000, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
+ {"Pentium MMX 233", CPU_PENTIUMMMX, fpus_builtin, 24, 233333333, 4, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, (7*8)/2},
+ {"Mobile Pentium MMX 120", CPU_PENTIUMMMX, fpus_builtin, 14, 120000000, 2, 30000000, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
+ {"Mobile Pentium MMX 133", CPU_PENTIUMMMX, fpus_builtin, 16, 133333333, 2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
+ {"Mobile Pentium MMX 150", CPU_PENTIUMMMX, fpus_builtin, 17, 150000000, 3, 30000000, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
+ {"Mobile Pentium MMX 166", CPU_PENTIUMMMX, fpus_builtin, 19, 166666666, 3, 33333333, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
+ {"Mobile Pentium MMX 200", CPU_PENTIUMMMX, fpus_builtin, 21, 200000000, 3, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
+ {"Mobile Pentium MMX 233", CPU_PENTIUMMMX, fpus_builtin, 24, 233333333, 4, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, (7*8)/2},
+ {"Mobile Pentium MMX 266", CPU_PENTIUMMMX, fpus_builtin, 26, 266666666, 4, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 4*8},
+ {"Mobile Pentium MMX 300", CPU_PENTIUMMMX, fpus_builtin, 28, 300000000, 5, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, (9*8)/2},
+ {"Pentium OverDrive 125", CPU_PENTIUM, fpus_builtin, 15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2},
+ {"Pentium OverDrive 150", CPU_PENTIUM, fpus_builtin, 17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
+ {"Pentium OverDrive 166", CPU_PENTIUM, fpus_builtin, 17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
+ {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, fpus_builtin, 15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2},
+ {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, fpus_builtin, 17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
+ {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, fpus_builtin, 19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
+ {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, fpus_builtin, 20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*7},
+ {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, fpus_builtin, 21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
{"", -1, 0, 0, 0}
};
CPU cpus_K6_S7[] =
{
/*AMD K6*/
- {"K6/166", CPU_K6, 19, 166666666, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
- {"K6/200", CPU_K6, 21, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24},
- {"K6/233", CPU_K6, 24, 233333333, 4, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
- {"K6/266", CPU_K6, 26, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
- {"K6/300", CPU_K6, 28, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
- {"K6-2/233", CPU_K6_2, 24, 233333333, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
- {"K6-2/266", CPU_K6_2, 26, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
- {"K6-2/300 AFR-66", CPU_K6_2, 28, 300000000, 5, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
+ {"K6/166", CPU_K6, fpus_builtin, 19, 166666666, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
+ {"K6/200", CPU_K6, fpus_builtin, 21, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24},
+ {"K6/233", CPU_K6, fpus_builtin, 24, 233333333, 4, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
+ {"K6/266", CPU_K6, fpus_builtin, 26, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
+ {"K6/300", CPU_K6, fpus_builtin, 28, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
+ {"K6-2/233", CPU_K6_2, fpus_builtin, 24, 233333333, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
+ {"K6-2/266", CPU_K6_2, fpus_builtin, 26, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
+ {"K6-2/300 AFR-66", CPU_K6_2, fpus_builtin, 28, 300000000, 5, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
{"", -1, 0, 0, 0}
};
CPU cpus_K6_SS7[] =
{
/*AMD K6*/
- {"K6/166", CPU_K6, 19, 166666666, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
- {"K6/200", CPU_K6, 21, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24},
- {"K6/233", CPU_K6, 24, 233333333, 4, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
- {"K6/266", CPU_K6, 26, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
- {"K6/300", CPU_K6, 28, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
- {"K6-2/233", CPU_K6_2, 24, 233333333, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
- {"K6-2/266", CPU_K6_2, 26, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
- {"K6-2/300", CPU_K6_2, 28, 300000000, 5, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
- {"K6-2/333", CPU_K6_2, 28, 333333333, 5, 31666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40},
- {"K6-2/350", CPU_K6_2, 28, 350000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 42},
- {"K6-2/366", CPU_K6_2, 28, 366666666, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 44},
- {"K6-2/380", CPU_K6_2, 28, 380000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 46},
- {"K6-2/400", CPU_K6_2, 28, 400000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48},
- {"K6-2/450", CPU_K6_2, 28, 450000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54},
- {"K6-2/475", CPU_K6_2, 28, 475000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57},
- {"K6-2/500", CPU_K6_2, 28, 500000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60},
- {"K6-2/533", CPU_K6_2, 28, 533333333, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 64},
- {"K6-2/550", CPU_K6_2, 28, 550000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 66},
- {"K6-2+/450", CPU_K6_2P, 28, 450000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54},
- {"K6-2+/475", CPU_K6_2P, 28, 475000000, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57},
- {"K6-2+/500", CPU_K6_2P, 28, 500000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60},
- {"K6-2+/533", CPU_K6_2P, 28, 533333333, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 64},
- {"K6-2+/550", CPU_K6_2P, 28, 550000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 66},
- {"K6-III/400", CPU_K6_3, 28, 400000000, 5, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48},
- {"K6-III/450", CPU_K6_3, 28, 450000000, 5, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54},
- {"K6-III+/400", CPU_K6_3P, 28, 400000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48},
- {"K6-III+/450", CPU_K6_3P, 28, 450000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54},
- {"K6-III+/475", CPU_K6_3P, 28, 475000000, 5, 31666667, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57},
- {"K6-III+/500", CPU_K6_3P, 28, 500000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60},
+ {"K6/166", CPU_K6, fpus_builtin, 19, 166666666, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
+ {"K6/200", CPU_K6, fpus_builtin, 21, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24},
+ {"K6/233", CPU_K6, fpus_builtin, 24, 233333333, 4, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
+ {"K6/266", CPU_K6, fpus_builtin, 26, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
+ {"K6/300", CPU_K6, fpus_builtin, 28, 300000000, 5, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
+ {"K6-2/233", CPU_K6_2, fpus_builtin, 24, 233333333, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
+ {"K6-2/266", CPU_K6_2, fpus_builtin, 26, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
+ {"K6-2/300", CPU_K6_2, fpus_builtin, 28, 300000000, 5, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
+ {"K6-2/333", CPU_K6_2, fpus_builtin, 28, 333333333, 5, 31666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40},
+ {"K6-2/350", CPU_K6_2, fpus_builtin, 28, 350000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 42},
+ {"K6-2/366", CPU_K6_2, fpus_builtin, 28, 366666666, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 44},
+ {"K6-2/380", CPU_K6_2, fpus_builtin, 28, 380000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 46},
+ {"K6-2/400", CPU_K6_2, fpus_builtin, 28, 400000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48},
+ {"K6-2/450", CPU_K6_2, fpus_builtin, 28, 450000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54},
+ {"K6-2/475", CPU_K6_2, fpus_builtin, 28, 475000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57},
+ {"K6-2/500", CPU_K6_2, fpus_builtin, 28, 500000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60},
+ {"K6-2/533", CPU_K6_2, fpus_builtin, 28, 533333333, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 64},
+ {"K6-2/550", CPU_K6_2, fpus_builtin, 28, 550000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 66},
+ {"K6-2+/450", CPU_K6_2P, fpus_builtin, 28, 450000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54},
+ {"K6-2+/475", CPU_K6_2P, fpus_builtin, 28, 475000000, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57},
+ {"K6-2+/500", CPU_K6_2P, fpus_builtin, 28, 500000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60},
+ {"K6-2+/533", CPU_K6_2P, fpus_builtin, 28, 533333333, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 64},
+ {"K6-2+/550", CPU_K6_2P, fpus_builtin, 28, 550000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 66},
+ {"K6-III/400", CPU_K6_3, fpus_builtin, 28, 400000000, 5, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48},
+ {"K6-III/450", CPU_K6_3, fpus_builtin, 28, 450000000, 5, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54},
+ {"K6-III+/400", CPU_K6_3P, fpus_builtin, 28, 400000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 48},
+ {"K6-III+/450", CPU_K6_3P, fpus_builtin, 28, 450000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 54},
+ {"K6-III+/475", CPU_K6_3P, fpus_builtin, 28, 475000000, 5, 31666667, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 57},
+ {"K6-III+/500", CPU_K6_3P, fpus_builtin, 28, 500000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 60},
{"", -1, 0, 0, 0}
};
+CPU cpus_PentiumPro[] =
+{
+ /*Intel Pentium Pro*/
+ {"Pentium Pro 150", CPU_PENTIUMPRO, fpus_builtin, 17, 150000000, 3, 30000000, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
+ {"Pentium Pro 166", CPU_PENTIUMPRO, fpus_builtin, 19, 166666666, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
+ {"Pentium Pro 180", CPU_PENTIUMPRO, fpus_builtin, 20, 180000000, 3, 30000000, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
+ {"Pentium Pro 200", CPU_PENTIUMPRO, fpus_builtin, 21, 200000000, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
+ {"Pentium II Overdrive 300", CPU_PENTIUM_2, fpus_builtin, 20, 300000000, 3, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 36},
+ {"Pentium II Overdrive 333", CPU_PENTIUM_2, fpus_builtin, 21, 333333333, 3, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 40},
+ {"", -1, 0, 0, 0}
+};
+
+CPU cpus_Slot1_100MHz[] =
+{
+ /*Intel Pentium II*/
+ {"Pentium II/233", CPU_PENTIUM_2, fpus_builtin, 20, 233333333, 3, 33333333, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 28},
+ {"Pentium II/266", CPU_PENTIUM_2, fpus_builtin, 20, 266666666, 3, 33333333, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 32},
+ {"Pentium II/300", CPU_PENTIUM_2, fpus_builtin, 20, 300000000, 3, 33333333, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 36},
+ {"Pentium II/333", CPU_PENTIUM_2, fpus_builtin, 20, 333333333, 3, 33333333, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 40},
+ {"Pentium II/350", CPU_PENTIUM_2, fpus_builtin, 20, 350000000, 3, 33333333, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 42},
+ {"Pentium II/400", CPU_PENTIUM_2, fpus_builtin, 20, 400000000, 3, 33333333, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 48},
+ {"Pentium II/450", CPU_PENTIUM_2, fpus_builtin, 20, 450000000, 3, 33333333, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 54},
+ {"Celeron 266", CPU_CELERON, fpus_builtin, 20, 266666666, 3, 33333333, 0x650, 0x650, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 32},
+ {"Celeron 300", CPU_CELERON, fpus_builtin, 20, 300000000, 3, 33333333, 0x650, 0x650, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 36},
+ {"Celeron-A 300", CPU_CELERON_A, fpus_builtin, 20, 300000000, 3, 33333333, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 40},
+ {"Celeron 333", CPU_CELERON_A, fpus_builtin, 20, 333333333, 3, 33333333, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 44},
+ {"Celeron 366", CPU_CELERON_A, fpus_builtin, 20, 366666666, 3, 33333333, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 48},
+ {"Celeron 400", CPU_CELERON_A, fpus_builtin, 20, 400000000, 3, 33333333, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 52},
+ {"Celeron 433", CPU_CELERON_A, fpus_builtin, 20, 433333333, 3, 33333333, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 56},
+ {"Celeron 466", CPU_CELERON_A, fpus_builtin, 20, 466666666, 3, 33333333, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 60},
+ {"Celeron 500", CPU_CELERON_A, fpus_builtin, 20, 500000000, 3, 33333333, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 64},
+ {"Celeron 533", CPU_CELERON_A, fpus_builtin, 20, 533333333, 3, 33333333, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 68},
+ {"", -1, 0, 0, 0}
+};
+
+CPU cpus_VIA_100MHz[] =
+{
+ /*VIA Cyrix III*/
+ {"Cyrix III/500", CPU_CYRIX_III, fpus_builtin, 20, 500000000, 3, 33333333, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 64},
+/*Below are disabled as Windows 98 won't boot. This is most likely a limitation of the timer system*/
+/* {"Cyrix III/550", CPU_CYRIX_III, fpus_builtin, 20, 550000000, 3, 33333333, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 70},
+ {"Cyrix III/600", CPU_CYRIX_III, fpus_builtin, 20, 600000000, 3, 33333333, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 76},
+ {"Cyrix III/650", CPU_CYRIX_III, fpus_builtin, 20, 650000000, 3, 33333333, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 82},
+ {"Cyrix III/700", CPU_CYRIX_III, fpus_builtin, 20, 700000000, 3, 33333333, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 88},
+ {"C3/750", CPU_CYRIX_III, fpus_builtin, 20, 750000000, 3, 33333333, 0x673, 0x673, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 94},
+ {"C3/800", CPU_CYRIX_III, fpus_builtin, 20, 800000000, 3, 33333333, 0x673, 0x673, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 100},*/
+ {"", -1, 0, 0, 0}
+};
diff --git a/src/cs8230.c b/src/cs8230.c
new file mode 100644
index 0000000..c2125ed
--- /dev/null
+++ b/src/cs8230.c
@@ -0,0 +1,120 @@
+/*CS8230 CHIPSet consists of :
+ 82c301 bus controller
+ 82c302 page/interleave memory controller
+ 82a303 high address buffer
+ 82a304 low address buffer
+ 82b305 data buffer
+ 82a306 control buffer*/
+#include "ibm.h"
+#include "cs8230.h"
+#include "io.h"
+#include "mem.h"
+
+static struct
+{
+ int idx;
+ uint8_t regs[256];
+} cs8230;
+
+static void shadow_control(uint32_t addr, uint32_t size, int state)
+{
+// pclog("shadow_control: addr=%08x size=%04x state=%02x\n", addr, size, state);
+ switch (state)
+ {
+ case 0x00:
+ mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ case 0x01:
+ mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ case 0x10:
+ mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 0x11:
+ mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ }
+ flushmmucache_nopc();
+}
+
+static void rethink_shadow_mappings(void)
+{
+ int c;
+
+ for (c = 0; c < 4*8; c++) /*Addresses 40000-bffff in 16k blocks*/
+ {
+ if (cs8230.regs[0xa + (c >> 3)] & (1 << (c & 7)))
+ mem_set_mem_state(0x40000 + c*0x4000, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); /*IO channel*/
+ else
+ mem_set_mem_state(0x40000 + c*0x4000, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); /*System board*/
+ }
+ for (c = 0; c < 2*8; c++) /*Addresses c0000-fffff in 16k blocks. System board ROM can be mapped here*/
+ {
+ if (cs8230.regs[0xe + (c >> 3)] & (1 << (c & 7)))
+ mem_set_mem_state(0xc0000 + c*0x4000, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); /*IO channel*/
+ else
+ shadow_control(0xc0000 + c*0x4000, 0x4000, (cs8230.regs[9] >> (3-(c >> 2))) & 0x11);
+ }
+}
+
+static uint8_t cs8230_read(uint16_t port, void *p)
+{
+ uint8_t ret = 0xff;
+
+ if (port & 1)
+ {
+ switch (cs8230.idx)
+ {
+ case 0x04: /*82C301 ID/version*/
+ ret = cs8230.regs[cs8230.idx] & ~0xe3;
+ break;
+
+ case 0x08: /*82C302 ID/Version*/
+ ret = cs8230.regs[cs8230.idx] & ~0xe0;
+ break;
+
+ case 0x05: case 0x06: /*82C301 registers*/
+ case 0x09: case 0x0a: case 0x0b: case 0x0c: /*82C302 registers*/
+ case 0x0d: case 0x0e: case 0x0f:
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ case 0x28: case 0x29: case 0x2a:
+ ret = cs8230.regs[cs8230.idx];
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static void cs8230_write(uint16_t port, uint8_t val, void *p)
+{
+ if (!(port & 1))
+ cs8230.idx = val;
+ else
+ {
+// pclog("cs8230_write: reg=%02x val=%02x\n", cs8230.idx, val);
+ cs8230.regs[cs8230.idx] = val;
+ switch (cs8230.idx)
+ {
+ case 0x09: /*RAM/ROM Configuration in boot area*/
+ case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: /*Address maps*/
+ rethink_shadow_mappings();
+ break;
+ }
+ }
+}
+
+void cs8230_init(void)
+{
+ memset(&cs8230, 0, sizeof(cs8230));
+
+ io_sethandler(0x0022, 0x0002,
+ cs8230_read, NULL, NULL,
+ cs8230_write, NULL, NULL,
+ NULL);
+ if (mem_size > 768)
+ {
+ mem_mapping_set_addr(&ram_mid_mapping, 0xa0000, mem_size > 1024 ? 0x60000 : 0x20000 + (mem_size - 768) * 1024);
+ mem_mapping_set_exec(&ram_mid_mapping, ram + 0xa0000);
+ }
+}
diff --git a/src/cs8230.h b/src/cs8230.h
new file mode 100644
index 0000000..d4bd4a0
--- /dev/null
+++ b/src/cs8230.h
@@ -0,0 +1 @@
+void cs8230_init(void);
diff --git a/src/disc.c b/src/disc.c
index b2e0a0c..6b76b9b 100644
--- a/src/disc.c
+++ b/src/disc.c
@@ -143,7 +143,7 @@ void disc_poll()
{
disc_notfound--;
if (!disc_notfound)
- fdc_notfound();
+ fdc_notfound(FDC_STATUS_AM_NOT_FOUND);
}
}
diff --git a/src/disc.h b/src/disc.h
index d8e33a5..714af06 100644
--- a/src/disc.h
+++ b/src/disc.h
@@ -37,7 +37,7 @@ void fdc_callback();
int fdc_data(uint8_t dat);
void fdc_spindown();
void fdc_finishread();
-void fdc_notfound();
+void fdc_notfound(int reason);
void fdc_datacrcerror();
void fdc_headercrcerror();
void fdc_writeprotect();
diff --git a/src/disc_fdi.c b/src/disc_fdi.c
index 498a623..1393bc2 100644
--- a/src/disc_fdi.c
+++ b/src/disc_fdi.c
@@ -3,6 +3,7 @@
#include "ibm.h"
#include "disc.h"
#include "disc_fdi.h"
+#include "fdc.h"
#include "fdi2raw.h"
static struct
@@ -314,7 +315,7 @@ void fdi_poll()
if (fdi_revs == 3)
{
// pclog("Not found!\n");
- fdc_notfound();
+ fdc_notfound(FDC_STATUS_NOT_FOUND);
fdi_inread = fdi_inreadaddr = 0;
return;
}
diff --git a/src/disc_sector.c b/src/disc_sector.c
index b7805d6..26759bf 100644
--- a/src/disc_sector.c
+++ b/src/disc_sector.c
@@ -46,7 +46,9 @@ static int disc_intersector_delay = 0;
static uint8_t disc_sector_fill;
static int cur_sector, cur_byte;
static int index_count;
-
+
+static int disc_sector_status;
+
void disc_sector_reset(int drive, int side)
{
disc_sector_count[drive][side] = 0;
@@ -90,6 +92,8 @@ void disc_sector_readsector(int drive, int sector, int track, int side, int rate
disc_sector_sector = sector;
disc_sector_n = sector_size;
index_count = 0;
+
+ disc_sector_status = FDC_STATUS_AM_NOT_FOUND;
}
void disc_sector_writesector(int drive, int sector, int track, int side, int rate, int sector_size)
@@ -103,6 +107,8 @@ void disc_sector_writesector(int drive, int sector, int track, int side, int rat
disc_sector_sector = sector;
disc_sector_n = sector_size;
index_count = 0;
+
+ disc_sector_status = FDC_STATUS_AM_NOT_FOUND;
}
void disc_sector_readaddress(int drive, int track, int side, int rate)
@@ -114,6 +120,8 @@ void disc_sector_readaddress(int drive, int track, int side, int rate)
disc_sector_side = side;
disc_sector_drive = drive;
index_count = 0;
+
+ disc_sector_status = FDC_STATUS_AM_NOT_FOUND;
}
void disc_sector_format(int drive, int track, int side, int rate, uint8_t fill)
@@ -179,7 +187,7 @@ void disc_sector_poll()
if (index_count > 1)
{
// pclog("Find sector not found\n");
- fdc_notfound();
+ fdc_notfound(disc_sector_status);
disc_sector_state = STATE_IDLE;
break;
}
@@ -187,10 +195,11 @@ void disc_sector_poll()
disc_sector_side != s->h,
disc_sector_sector != s->r,
fdc_get_bitcell_period() != get_bitcell_period());*/
- if (cur_byte || disc_sector_track != s->c ||
- disc_sector_side != s->h ||
- disc_sector_sector != s->r ||
- disc_sector_n != s->n ||
+ if (!cur_byte && fdc_get_bitcell_period() == get_bitcell_period() &&
+ fdd_can_read_medium(disc_sector_drive ^ fdd_swap))
+ disc_sector_status = FDC_STATUS_NOT_FOUND; /*Disc readable, assume address marker found*/
+
+ if (cur_byte ||
fdc_get_bitcell_period() != get_bitcell_period() ||
!fdd_can_read_medium(disc_sector_drive ^ fdd_swap) ||
disc_intersector_delay)
@@ -198,6 +207,16 @@ void disc_sector_poll()
advance_byte();
break;
}
+ if (disc_sector_track != s->c ||
+ disc_sector_side != s->h ||
+ disc_sector_sector != s->r ||
+ disc_sector_n != s->n)
+ {
+ if (disc_sector_track != s->c)
+ disc_sector_status = (disc_sector_track == 0xff) ? FDC_STATUS_BAD_CYLINDER : FDC_STATUS_WRONG_CYLINDER;
+ advance_byte();
+ break;
+ }
disc_sector_state = STATE_READ_SECTOR;
case STATE_READ_SECTOR:
// pclog("STATE_READ_SECTOR: cur_byte=%i %i\n", cur_byte, disc_intersector_delay);
@@ -218,10 +237,14 @@ void disc_sector_poll()
if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap)))
{
// pclog("Medium is of a density not supported by the drive\n");
- fdc_notfound();
+ fdc_notfound(FDC_STATUS_AM_NOT_FOUND);
disc_sector_state = STATE_IDLE;
break;
}
+ if (!cur_byte && fdc_get_bitcell_period() == get_bitcell_period() &&
+ fdd_can_read_medium(disc_sector_drive ^ fdd_swap))
+ disc_sector_status = FDC_STATUS_NOT_FOUND; /*Disc readable, assume address marker found*/
+
if (cur_byte || !index_count || fdc_get_bitcell_period() != get_bitcell_period() ||
disc_intersector_delay)
{
@@ -244,14 +267,14 @@ void disc_sector_poll()
if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap)))
{
// pclog("Medium is of a density not supported by the drive\n");
- fdc_notfound();
+ fdc_notfound(FDC_STATUS_AM_NOT_FOUND);
disc_sector_state = STATE_IDLE;
break;
}
if (index_count)
{
// pclog("Find next sector hit end of track\n");
- fdc_notfound();
+ fdc_notfound(disc_sector_status);
disc_sector_state = STATE_IDLE;
break;
}
@@ -277,10 +300,15 @@ void disc_sector_poll()
if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap)))
{
// pclog("Medium is of a density not supported by the drive\n");
- fdc_notfound();
+ fdc_notfound(FDC_STATUS_AM_NOT_FOUND);
disc_sector_state = STATE_IDLE;
break;
}
+
+ if (!cur_byte && fdc_get_bitcell_period() == get_bitcell_period() &&
+ fdd_can_read_medium(disc_sector_drive ^ fdd_swap))
+ disc_sector_status = FDC_STATUS_NOT_FOUND; /*Disc readable, assume address marker found*/
+
if (writeprot[disc_sector_drive])
{
fdc_writeprotect();
@@ -290,20 +318,27 @@ void disc_sector_poll()
if (index_count > 1)
{
// pclog("Write find sector not found\n");
- fdc_notfound();
+ fdc_notfound(disc_sector_status);
disc_sector_state = STATE_IDLE;
break;
}
- if (cur_byte || disc_sector_track != s->c ||
- disc_sector_side != s->h ||
- disc_sector_sector != s->r ||
- disc_sector_n != s->n ||
+ if (cur_byte ||
fdc_get_bitcell_period() != get_bitcell_period() ||
disc_intersector_delay)
{
advance_byte();
break;
}
+ if (disc_sector_track != s->c ||
+ disc_sector_side != s->h ||
+ disc_sector_sector != s->r ||
+ disc_sector_n != s->n)
+ {
+ if (disc_sector_track != s->c)
+ disc_sector_status = (disc_sector_track == 0xff) ? FDC_STATUS_BAD_CYLINDER : FDC_STATUS_WRONG_CYLINDER;
+ advance_byte();
+ break;
+ }
disc_sector_state = STATE_WRITE_SECTOR;
case STATE_WRITE_SECTOR:
data = fdc_getdata(cur_byte == ((128 << s->n) - 1));
@@ -323,14 +358,19 @@ void disc_sector_poll()
if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap)))
{
// pclog("Medium is of a density not supported by the drive\n");
- fdc_notfound();
+ fdc_notfound(FDC_STATUS_AM_NOT_FOUND);
disc_sector_state = STATE_IDLE;
break;
}
+
+ if (!cur_byte && fdc_get_bitcell_period() == get_bitcell_period() &&
+ fdd_can_read_medium(disc_sector_drive ^ fdd_swap))
+ disc_sector_status = FDC_STATUS_NOT_FOUND; /*Disc readable, assume address marker found*/
+
if (index_count)
{
// pclog("Find next sector hit end of track\n");
- fdc_notfound();
+ fdc_notfound(disc_sector_status);
disc_sector_state = STATE_IDLE;
break;
}
@@ -343,6 +383,7 @@ void disc_sector_poll()
disc_sector_state = STATE_READ_ADDRESS;
case STATE_READ_ADDRESS:
fdc_sectorid(s->c, s->h, s->r, s->n, 0, 0);
+ advance_byte();
disc_sector_state = STATE_IDLE;
break;
@@ -362,13 +403,13 @@ void disc_sector_poll()
if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap)))
{
// pclog("Medium is of a density not supported by the drive\n");
- fdc_notfound();
+ fdc_notfound(FDC_STATUS_NOT_FOUND);
disc_sector_state = STATE_IDLE;
break;
}
if (fdc_get_bitcell_period() != get_bitcell_period())
{
- fdc_notfound();
+ fdc_notfound(FDC_STATUS_NOT_FOUND);
disc_sector_state = STATE_IDLE;
break;
}
diff --git a/src/f82c710_upc.c b/src/f82c710_upc.c
new file mode 100644
index 0000000..40dfd19
--- /dev/null
+++ b/src/f82c710_upc.c
@@ -0,0 +1,529 @@
+/*
+ * Chips & Technologies F82C710 Universal Peripheral Controller (UPC)
+ *
+ * Copyright (c) 2020 Eluan Costa Miranda All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * =============================================================================
+ *
+ * This SuperIO chip is commonly seem paired with the Single-chip AT (SCAT)
+ * chip. Only the functionality needed for the Hyundai Super-286TR BIOS is
+ * implented for now.
+ *
+ * One of the goals of this chip was getting rid of jumpers and have everything
+ * configured by software, but there is no configuration for serial and
+ * parallel IRQs. Because of that, motherboards still supply jumpers for these
+ * two signals.
+ *
+ */
+
+#include "ibm.h"
+
+#include "fdc.h"
+#include "ide.h"
+#include "io.h"
+#include "lpt.h"
+#include "serial.h"
+#include "x86.h"
+#include "keyboard_at.h"
+#include "pic.h"
+
+#define UPC_MOUSE_DEV_IDLE 0x01 /* bit 0, Device Idle */
+#define UPC_MOUSE_RX_FULL 0x02 /* bit 1, Device Char received */
+#define UPC_MOUSE_TX_IDLE 0x04 /* bit 2, Device XMIT Idle */
+#define UPC_MOUSE_RESET 0x08 /* bit 3, Device Reset */
+#define UPC_MOUSE_INTS_ON 0x10 /* bit 4, Device Interrupt On */
+#define UPC_MOUSE_ERROR_FLAG 0x20 /* bit 5, Device Error */
+#define UPC_MOUSE_CLEAR 0x40 /* bit 6, Device Clear */
+#define UPC_MOUSE_ENABLE 0x80 /* bit 7, Device Enable */
+
+typedef struct upc_t
+{
+ int configuration_state; // state of algorithm to enter configuration mode
+ int configuration_mode;
+ uint8_t next_value; // next expected value of configuration algorithm
+ uint16_t cri_addr; // cri = configuration index register, addr is even
+ uint16_t cap_addr; // cap = configuration access port, addr is odd and is cri_addr + 1
+ uint8_t cri; // currently indexed register
+
+ // these regs are not affected by reset
+ uint8_t regs[15]; // there are 16 indexes, but there is no need to store the last one which is: R = cri_addr / 4, W = exit config mode
+
+ int serial_irq;
+ int parallel_irq; // TODO: currently not implemented in PCem
+
+ int mouse_irq;
+ uint16_t mdata_addr; // Address of PS/2 data register
+ uint16_t mstat_addr; // Address of PS/2 status register
+ uint8_t mouse_status; // Mouse interface status register
+ uint8_t mouse_data; // Mouse interface data register
+ void (*mouse_write)(uint8_t val, void *p);
+ void *mouse_p;
+ pc_timer_t mouse_delay_timer;
+} upc_t;
+
+static upc_t upc;
+
+uint8_t upc_config_read(uint16_t port, void *priv);
+void upc_config_write(uint16_t port, uint8_t val, void *priv);
+
+void upc_mouse_disable(upc_t *upc);
+void upc_mouse_enable(upc_t *upc);
+uint8_t upc_mouse_read(uint16_t port, void *priv);
+void upc_mouse_write(uint16_t port, uint8_t val, void *priv);
+void upc_mouse_poll(void *priv);
+
+void upc_update_config(upc_t *upc)
+{
+ switch(upc->cri)
+ {
+ case 0:
+ if (upc->regs[0] & 0x4)
+ {
+ serial1_set(upc->regs[4] * 4, upc->serial_irq);
+ pclog("UPC: UART at %04X, irq %d\n", upc->regs[4] * 4, upc->serial_irq);
+ }
+ else
+ {
+ serial1_remove();
+ pclog("UPC: UART disabled\n");
+ }
+ if (upc->regs[0] & 0x8)
+ {
+ lpt1_init(upc->regs[6] * 4);
+ pclog("UPC: PARALLEL at %04X, irq %d\n", upc->regs[6] * 4, upc->parallel_irq);
+ }
+ else
+ {
+ lpt1_remove();
+ pclog("UPC: PARALLEL disabled\n");
+ }
+ if ((upc->regs[0] & 0x60) != 0)
+ pclog("UPC: Oscillator control not implemented!\n");
+ break;
+
+ case 1:
+ if ((upc->regs[1] & 0x80) != 0)
+ pclog("UPC: Restricted serial reset not implemented!\n");
+ if ((upc->regs[1] & 0x80) != 0)
+ pclog("UPC: Restricted serial reset not implemented!\n");
+ if ((upc->regs[1] & 0x40) != 0)
+ pclog("UPC: Bidirectional parallel port support not implemented!\n");
+ if ((upc->regs[1] & 0x38) != 0)
+ pclog("UPC: UART force CTS, DSR, DCD not implemented!\n");
+ break;
+
+ case 2:
+ if ((upc->regs[2] & 0x70) != 0)
+ pclog("UPC: UART clock control not implemented!\n");
+ break;
+
+ case 9:
+ if (upc->regs[9] == 0xb0)
+ pclog("UPC: GPCS not implemented! (at default address: %04X)\n", upc->regs[9] * 4);
+ else if (upc->regs[9] != 0)
+ pclog("UPC: GPCS not implemented! (at address: %04X)\n", upc->regs[9] * 4);
+ break;
+
+ case 12:
+ /* Adding the IDE and floppy controllers when they are already present causes problems.*/
+ /* FIX: remove floppy and IDE controllers before adding them again if needed. */
+ fdc_remove();
+ ide_pri_disable();
+ if ((upc->regs[12] & 0x40) != 0)
+ {
+ pclog("UPC: IDE XT mode not implemented!\n");
+ }
+ else
+ {
+ if (upc->regs[12] & 0x80)
+ {
+ ide_pri_enable();
+ pclog("UPC: AT IDE enabled\n");
+ }
+ else
+ {
+ pclog("UPC: AT IDE disabled\n");
+ }
+ }
+
+ if (upc->regs[12] & 0x20)
+ {
+ fdc_add();
+ pclog("UPC: FDC enabled\n");
+ }
+ else
+ {
+ pclog("UPC: FDC disabled\n");
+ }
+
+ if ((upc->regs[12] & 0x10) != 0)
+ pclog("UPC: FDC power down mode not implemented!\n");
+ if ((upc->regs[12] & 0x0C) != 0)
+ pclog("UPC: RTCCS not implemented!\n");
+ if ((upc->regs[12] & 0x01) != 0)
+ pclog("UPC: PS/2 mouse port power down not implemented!\n");
+ break;
+
+ case 13:
+ if (upc->regs[13] != 0)
+ {
+ upc->mdata_addr = upc->regs[13] * 4;
+ upc->mstat_addr = upc->mdata_addr + 1;
+ pclog("UPC: PS/2 mouse port at %04X, irq %d\n", upc->mdata_addr, upc->mouse_irq);
+ upc_mouse_enable(upc);
+ }
+ else
+ {
+ pclog("UPC: PS/2 mouse port disabled\n");
+ upc_mouse_disable(upc);
+ }
+
+ case 14:
+ if (upc->regs[14] != 0)
+ pclog("UPC: Test mode not implemented!\n");
+ break;
+ }
+}
+
+uint8_t upc_config_read(uint16_t port, void *priv)
+{
+ upc_t *upc = (upc_t *)priv;
+ uint8_t temp = 0xff;
+
+ if (upc->configuration_mode)
+ {
+ if (port == upc->cri_addr)
+ {
+ temp = upc->cri;
+ }
+ else if (port == upc->cap_addr)
+ {
+ if (upc->cri == 0xf)
+ temp = upc->cri_addr / 4;
+ else
+ temp = upc->regs[upc->cri];
+ }
+ }
+
+// pclog("UPC READ : %04X, %02X\n", port, temp);
+ return temp;
+}
+
+void upc_config_write(uint16_t port, uint8_t val, void *priv)
+{
+ upc_t *upc = (upc_t *)priv;
+ int configuration_state_event = 0;
+
+// pclog("UPC WRITE: %04X, %02X\n", port, val);
+
+ switch(port)
+ {
+ case 0x2fa:
+ /* Execute configuration step 1 for any value except 9, ff or 36 */
+ if (upc->configuration_state == 0)
+ {
+ configuration_state_event = 1;
+ /* next value should be the 1's complement of the current one */
+ upc->next_value = 0xff - val;
+ }
+ else if (upc->configuration_state == 4)
+ {
+ uint8_t addr_verify = upc->cri_addr / 4;
+ addr_verify += val;
+ if (addr_verify == 0xff)
+ {
+ upc->configuration_mode = 1;
+ // TODO: is the value of cri reset here or when exiting configuration mode?
+ io_sethandler(upc->cri_addr, 0x0002, upc_config_read, NULL, NULL, upc_config_write, NULL, NULL, upc);
+ pclog("UPC: in configuration mode at %04X\n", upc->cri_addr);
+ }
+ else
+ {
+ upc->configuration_mode = 0;
+ pclog("UPC: configuration mode failed (sum = %02X)\n", addr_verify);
+ }
+ }
+ break;
+ case 0x3fa:
+ /* go to configuration step 2 if value is the expected one */
+ if (upc->configuration_state == 1 && val == upc->next_value)
+ configuration_state_event = 1;
+ else if (upc->configuration_state == 2 && val == 0x36)
+ configuration_state_event = 1;
+ else if (upc->configuration_state == 3)
+ {
+ upc->cri_addr = val * 4;
+ upc->cap_addr = upc->cri_addr + 1;
+ configuration_state_event = 1;
+ }
+ break;
+ default:
+ break;
+ }
+ if (upc->configuration_mode)
+ {
+ if (port == upc->cri_addr)
+ {
+ upc->cri = val & 0xf;
+
+ }
+ else if (port == upc->cap_addr)
+ {
+ if (upc->cri == 0xf)
+ {
+ pclog("UPC: exiting configuration mode\n");
+ upc->configuration_mode = 0;
+ io_removehandler(upc->cri_addr, 0x0002, upc_config_read, NULL, NULL, upc_config_write, NULL, NULL, upc);
+ }
+ else
+ {
+ upc->regs[upc->cri] = val;
+ /* configuration should be updated at each register write, otherwise PC5086 do not detect ports correctly */
+ upc_update_config(upc);
+ }
+ }
+ }
+
+ // TODO: is the state only reset when accessing 0x2fa and 0x3fa wrongly?
+ if ((port == 0x2fa || port == 0x3fa) && configuration_state_event)
+ upc->configuration_state++;
+ else
+ upc->configuration_state = 0;
+}
+
+static void *upc_init()
+{
+ pclog("UPC INIT\n");
+
+ /* Disable all peripherals. upc_update_config will enable configured peripherals */
+ serial1_remove();
+ serial2_remove();
+ lpt1_remove();
+ lpt2_remove();
+ fdc_remove();
+ ide_pri_disable();
+ ide_sec_disable();
+ serial1_set_has_fifo(0);
+
+ memset(&upc, 0, sizeof(upc));
+
+ upc.serial_irq = device_get_config_int("serial_irq");
+ upc.parallel_irq = device_get_config_int("parallel_irq");
+
+ // because of these addresses, serial ports must be 16450 without fifos
+ io_sethandler(0x02fa, 0x0001, NULL, NULL, NULL, upc_config_write, NULL, NULL, &upc);
+ io_sethandler(0x03fa, 0x0001, NULL, NULL, NULL, upc_config_write, NULL, NULL, &upc);
+
+ upc.regs[0] = 0x0c;
+ upc.regs[1] = 0x00;
+ upc.regs[2] = 0x00;
+ upc.regs[3] = 0x00;
+ upc.regs[4] = 0xfe;
+ upc.regs[5] = 0x00;
+ upc.regs[6] = 0x9e;
+ upc.regs[7] = 0x00;
+ upc.regs[8] = 0x00;
+ upc.regs[9] = 0xb0;
+ upc.regs[10] = 0x00;
+ upc.regs[11] = 0x00;
+ upc.regs[12] = 0xa0;
+ upc.regs[13] = 0x00;
+ upc.regs[14] = 0x00;
+
+ for (upc.cri = 0; upc.cri < 15; upc.cri++)
+ upc_update_config(&upc);
+ upc.cri = 0;
+
+ /********************* Initialize mouse interface ********************/
+ if(romset == ROM_PC5086) /* IRQ is 2 for PC5086 and 12 for others */
+ upc.mouse_irq = 2;
+ else
+ upc.mouse_irq = 12;
+ upc.mdata_addr = upc.regs[13] * 4;
+ upc.mstat_addr = upc.mdata_addr + 1;
+ upc.mouse_status = UPC_MOUSE_DEV_IDLE | UPC_MOUSE_TX_IDLE;
+ upc.mouse_data = 0xff;
+ /* Set timer for mouse polling */
+ timer_add(&upc.mouse_delay_timer, upc_mouse_poll, &upc, 1);
+
+ return &upc;
+}
+
+static device_config_t upc_config[] =
+{
+ {
+ .name = "serial_irq",
+ .description = "Serial Port IRQ",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "IRQ 4 (for address 0x3F8/COM1)",
+ .value = 4
+ },
+ {
+ .description = "IRQ 3 (for address 0x2F8/COM2)",
+ .value = 3
+ },
+ {
+ .description = "Disabled",
+ .value = 0 // TODO: see if this breaks PCem's PIC
+ }
+ },
+ .default_int = 4
+ },
+ {
+ .name = "parallel_irq",
+ .description = "Parallel Port IRQ",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "IRQ 7 (for address 0x378/LPTB)",
+ .value = 7
+ },
+ {
+ .description = "IRQ 5 (for address 0x278/LPTC)",
+ .value = 5
+ },
+ {
+ .description = "Disabled",
+ .value = 0 // TODO: see if this breaks PCem's PIC
+ }
+ },
+ .default_int = 7
+ },
+ // For the Hyundai Super-286TR, the only other jumper is the Color/Mono one and it's handled by the at keyboard controller code.
+ {
+ .type = -1
+ }
+};
+
+
+device_t f82c710_upc_device =
+{
+ "F82C710 UPC",
+ 0,
+ upc_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ upc_config
+};
+
+/****************** PS/2 mouse port *********************/
+uint8_t upc_mouse_read(uint16_t port, void *priv)
+{
+ upc_t *upc = (upc_t *)priv;
+ uint8_t temp = 0xff;
+ if (port == upc->mstat_addr)
+ {
+ temp = upc->mouse_status;
+ }
+
+ if (port == upc->mdata_addr && (upc->mouse_status & UPC_MOUSE_RX_FULL))
+ {
+ temp = upc->mouse_data;
+ upc->mouse_data = 0xff;
+ upc->mouse_status &= ~UPC_MOUSE_RX_FULL;
+ upc->mouse_status |= UPC_MOUSE_DEV_IDLE;
+ // pclog("%04X:%04X UPC mouse READ: %04X, %02X\n", CS, cpu_state.pc, port, temp);
+ }
+
+ // pclog("%04X:%04X UPC mouse READ: %04X, %02X\n", CS, cpu_state.pc, port, temp);
+ return temp;
+}
+
+void upc_mouse_write(uint16_t port, uint8_t val, void *priv)
+{
+ // pclog("%04X:%04X UPC mouse WRITE: %04X, %02X\n", CS, cpu_state.pc, port, val);
+
+ upc_t *upc = (upc_t *)priv;
+ if (port == upc->mstat_addr)
+ {
+ /* write status bits
+ * DEV_IDLE, TX_IDLE, RX_FULL and ERROR_FLAG bits are unchanged
+ */
+ upc->mouse_status = (val & 0xD8) | (upc->mouse_status & 0x27);
+ if (upc->mouse_status & UPC_MOUSE_ENABLE)
+ mouse_scan = 1;
+ else
+ mouse_scan = 0;
+ if (upc->mouse_status & (UPC_MOUSE_CLEAR | UPC_MOUSE_RESET))
+ {
+ /* if CLEAR or RESET bit is set, clear mouse queue */
+ mouse_queue_start = mouse_queue_end;
+ upc->mouse_status &= ~UPC_MOUSE_RX_FULL;
+ upc->mouse_status |= UPC_MOUSE_DEV_IDLE | UPC_MOUSE_TX_IDLE;
+ mouse_scan = 0;
+ }
+ }
+
+ if (port == upc->mdata_addr)
+ {
+ if ((upc->mouse_status & UPC_MOUSE_TX_IDLE) && (upc->mouse_status & UPC_MOUSE_ENABLE))
+ {
+ upc->mouse_data = val;
+ if (upc->mouse_write)
+ upc->mouse_write(val, upc->mouse_p);
+ }
+ }
+}
+
+void upc_mouse_disable(upc_t *upc)
+{
+ io_removehandler(upc->mdata_addr, 0x0002, upc_mouse_read, NULL, NULL, upc_mouse_write, NULL, NULL, upc);
+}
+
+void upc_mouse_enable(upc_t *upc)
+{
+ io_sethandler(upc->mdata_addr, 0x0002, upc_mouse_read, NULL, NULL, upc_mouse_write, NULL, NULL, upc);
+}
+
+void upc_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p)
+{
+ upc.mouse_write = mouse_write;
+ upc.mouse_p = p;
+}
+
+void upc_mouse_poll(void *priv)
+{
+ upc_t *upc = (upc_t *)priv;
+ timer_advance_u64(&upc->mouse_delay_timer, (1000 * TIMER_USEC));
+
+ /* check if there is something in the mouse queue */
+ if (mouse_queue_start != mouse_queue_end)
+ {
+ // pclog("Mouse timer. %d %d %02X %02X\n", mouse_queue_start, mouse_queue_end, upc->mouse_status, upc->mouse_data);
+ if ((upc->mouse_status & UPC_MOUSE_ENABLE) && !(upc->mouse_status & UPC_MOUSE_RX_FULL))
+ {
+ upc->mouse_data = mouse_queue[mouse_queue_start];
+ mouse_queue_start = (mouse_queue_start + 1) & 0xf;
+ /* update mouse status */
+ upc->mouse_status |= UPC_MOUSE_RX_FULL;
+ upc->mouse_status &= ~(UPC_MOUSE_DEV_IDLE);
+ // pclog("Reading %02X from the mouse queue at %i %i. New status is %02X\n", upc->mouse_data, mouse_queue_start, mouse_queue_end, upc->mouse_status);
+ /* raise IRQ if enabled */
+ if (upc->mouse_status & UPC_MOUSE_INTS_ON)
+ {
+ picint(1 << upc->mouse_irq);
+ // pclog("upc_mouse : take IRQ %d\n", upc->mouse_irq);
+ }
+ }
+ }
+}
diff --git a/src/f82c710_upc.h b/src/f82c710_upc.h
new file mode 100644
index 0000000..05764af
--- /dev/null
+++ b/src/f82c710_upc.h
@@ -0,0 +1,6 @@
+#include "device.h"
+
+void upc_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p);
+
+extern device_t f82c710_upc_device;
+
diff --git a/src/fdc.c b/src/fdc.c
index 308599f..eb70169 100644
--- a/src/fdc.c
+++ b/src/fdc.c
@@ -5,12 +5,23 @@
#include "disc.h"
#include "disc_sector.h"
#include "dma.h"
+#include "fdc.h"
#include "fdd.h"
#include "io.h"
#include "pic.h"
#include "timer.h"
#include "x86.h"
+#define ST1_DE (1 << 5)
+#define ST1_ND (1 << 2)
+#define ST1_NW (1 << 1)
+#define ST1_MA (1 << 0)
+
+#define ST2_DD (1 << 5)
+#define ST2_WC (1 << 4) /*Wrong cylinder*/
+#define ST2_BC (1 << 1) /*Bad cylinder*/
+#define ST2_MD (1 << 0)
+
static int fdc_reset_stat = 0;
/*FDC*/
typedef struct FDC
@@ -34,8 +45,7 @@ typedef struct FDC
int format_state;
int tc;
int written;
- int in_seek_mt;
-
+
int pcjr, ps1;
pc_timer_t watchdog_timer;
@@ -87,7 +97,7 @@ void fdc_reset()
fdc.lock = 0;
fdc.head = 0;
fdc.abort = 0;
- if (!AT && romset != ROM_XI8088)
+ if (!AT && romset != ROM_XI8088 && romset != ROM_PC5086)
{
fdc.rate = 2;
// fdc_update_rate();
@@ -349,11 +359,6 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
}
else
{
- if (val&4)
- {
- fdc.stat=0x80;
- fdc.pnum=fdc.ptot=0;
- }
if ((val&4) && !(fdc.dor&4))
{
timer_set_delay_u64(&fdc.timer, 8 * TIMER_USEC);
@@ -404,11 +409,10 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
{
fdc.tc = 0;
fdc.data_ready = 0;
- fdc.in_seek_mt = 0;
-
+
fdc.command=val;
// pclog("Starting FDC command %02X\n",fdc.command);
- switch (fdc.command&0x1F)
+ switch (fdc.command)
{
case 1: /*Mode*/
if (!fdc.is_nsc) goto bad_command;
@@ -419,23 +423,23 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.format_state = 0;
break;
- case 2: /*Read track*/
+ case 0x02: case 0x42: /*Read track*/
fdc.pnum=0;
fdc.ptot=8;
fdc.stat=0x90;
fdc.pos=0;
break;
- case 3: /*Specify*/
+ case 0x03: /*Specify*/
fdc.pnum=0;
fdc.ptot=2;
fdc.stat=0x90;
break;
- case 4: /*Sense drive status*/
+ case 0x04: /*Sense drive status*/
fdc.pnum=0;
fdc.ptot=1;
fdc.stat=0x90;
break;
- case 5: /*Write data*/
+ case 0x05: case 0x45: case 0x85: case 0xc5: /*Write data*/
// printf("Write data!\n");
fdc.pnum=0;
fdc.ptot=8;
@@ -443,18 +447,19 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.pos=0;
// readflash=1;
break;
- case 6: /*Read data*/
+ case 0x06: case 0x26: case 0x46: case 0x66: /*Read data*/
+ case 0x86: case 0xa6: case 0xc6: case 0xe6:
fdc.pnum=0;
fdc.ptot=8;
fdc.stat=0x90;
fdc.pos=0;
break;
- case 7: /*Recalibrate*/
+ case 0x07: /*Recalibrate*/
fdc.pnum=0;
fdc.ptot=1;
fdc.stat=0x90;
break;
- case 8: /*Sense interrupt status*/
+ case 0x08: /*Sense interrupt status*/
if (fdc.int_pending || fdc_reset_stat)
{
// printf("Sense interrupt status %i\n",curdrive);
@@ -471,20 +476,20 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
timer_set_delay_u64(&fdc.timer, 100 * TIMER_USEC);
}
break;
- case 10: /*Read sector ID*/
+ case 0x0a: case 0x4a: /*Read sector ID*/
fdc.pnum=0;
fdc.ptot=1;
fdc.stat=0x90;
fdc.pos=0;
break;
- case 0x0d: /*Format track*/
+ case 0x0d: case 0x4d: case 0x8d: case 0xcd: /*Format track*/
fdc.pnum=0;
fdc.ptot=5;
fdc.stat=0x90;
fdc.pos=0;
fdc.format_state = 0;
break;
- case 15: /*Seek*/
+ case 0x0f: /*Seek*/
fdc.pnum=0;
fdc.ptot=2;
fdc.stat=0x90;
@@ -552,15 +557,15 @@ bad_command:
// pclog("Got all params %02X\n", fdc.command);
fdc.stat=0x30;
- discint=fdc.command&0x1F;
timer_set_delay_u64(&fdc.timer, 256 * TIMER_USEC);
// fdc.drive = fdc.params[0] & 3;
disc_drivesel = fdc.drive & 1;
fdc_reset_stat = 0;
disc_set_drivesel(fdc.drive & 1);
- switch (discint)
+ discint = fdc.command & 0x1f;
+ switch (fdc.command)
{
- case 2: /*Read a track*/
+ case 0x02: case 0x42: /*Read track*/
fdc_rate(fdc.drive);
fdc.head=fdc.params[2];
fdc.sector=fdc.params[3];
@@ -576,7 +581,7 @@ bad_command:
fdc.inread = 1;
break;
- case 3: /*Specify*/
+ case 0x03: /*Specify*/
fdc.stat=0x80;
fdc.specify[0] = fdc.params[0];
fdc.specify[1] = fdc.params[1];
@@ -584,18 +589,20 @@ bad_command:
timer_disable(&fdc.timer);
break;
- case 5: /*Write data*/
+ case 0x05: case 0x45: case 0x85: case 0xc5: /*Write data*/
fdc_rate(fdc.drive);
fdc.head=fdc.params[2];
fdc.sector=fdc.params[3];
fdc.sector_size = fdc.params[4];
fdc.eot[fdc.drive] = fdc.params[5];
- if (fdc.config & 0x40)
- fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]);
- fdc.track[fdc.drive]=fdc.params[1];
fdc.rw_track = fdc.params[1];
-
- disc_writesector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]);
+ if (fdc.config & 0x40)
+ {
+ fdd_seek(fdc.drive, fdc.rw_track - fdc.track[fdc.drive]);
+ fdc.track[fdc.drive] = fdc.rw_track;
+ }
+
+ disc_writesector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]);
timer_disable(&fdc.timer);
fdc.written = 0;
readflash_set(READFLASH_FDC, fdc.drive);
@@ -605,24 +612,27 @@ bad_command:
// ioc_fiq(IOC_FIQ_DISC_DATA);
break;
- case 6: /*Read data*/
+ case 0x06: case 0x26: case 0x46: case 0x66: /*Read data*/
+ case 0x86: case 0xa6: case 0xc6: case 0xe6:
fdc_rate(fdc.drive);
fdc.head=fdc.params[2];
fdc.sector=fdc.params[3];
fdc.sector_size = fdc.params[4];
fdc.eot[fdc.drive] = fdc.params[5];
- if (fdc.config & 0x40)
- fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]);
- fdc.track[fdc.drive]=fdc.params[1];
fdc.rw_track = fdc.params[1];
+ if (fdc.config & 0x40)
+ {
+ fdd_seek(fdc.drive, fdc.rw_track - fdc.track[fdc.drive]);
+ fdc.track[fdc.drive] = fdc.rw_track;
+ }
- disc_readsector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]);
+ disc_readsector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]);
timer_disable(&fdc.timer);
readflash_set(READFLASH_FDC, fdc.drive);
fdc.inread = 1;
break;
- case 7: /*Recalibrate*/
+ case 0x07: /*Recalibrate*/
fdc.stat = 1 << fdc.drive;
timer_disable(&fdc.timer);
time = fdd_seek(fdc.drive, SEEK_RECALIBRATE);
@@ -630,7 +640,7 @@ bad_command:
timer_set_delay_u64(&fdc.timer, time);
break;
- case 0x0d: /*Format*/
+ case 0x0d: case 0x4d: case 0x8d: case 0xcd: /*Format*/
fdc_rate(fdc.drive);
fdc.head = (fdc.params[0] & 4) ? 1 : 0;
fdc.format_state = 1;
@@ -638,9 +648,9 @@ bad_command:
fdc.stat = 0x30;
break;
- case 0xf: /*Seek*/
+ case 0x0f: /*Seek*/
fdc.stat = 1 << fdc.drive;
- fdc.head = (fdc.params[0] & 4) ? 1 : 0;
+ fdc.head = 0;
timer_disable(&fdc.timer);
time = fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]);
if (time)
@@ -648,19 +658,23 @@ bad_command:
// pclog("Seek to %i\n", fdc.params[1]);
break;
- case 10: /*Read sector ID*/
+ case 0x0a: case 0x4a: /*Read sector ID*/
fdc_rate(fdc.drive);
timer_disable(&fdc.timer);
fdc.head = (fdc.params[0] & 4) ? 1 : 0;
// pclog("Read sector ID %i %i\n", fdc.rate, fdc.drive);
disc_readaddress(fdc.drive, fdc.track[fdc.drive], fdc.head, fdc.rate);
break;
+
+ case 0x94: /*Unlock*/
+ discint = 0x94;
+ break;
}
}
}
return;
case 7:
- if (!AT && romset != ROM_XI8088)
+ if (!AT && romset != ROM_XI8088 && romset != ROM_PC5086)
return;
fdc.rate=val&3;
@@ -760,10 +774,6 @@ uint8_t fdc_read(uint16_t addr, void *priv)
temp=fdc.dat;
fdc.data_ready = 0;
}
- if (discint==0xA)
- {
- timer_set_delay_u64(&fdc.timer, 1024 * TIMER_USEC);
- }
fdc.stat &= 0xf0;
break;
case 7: /*Disk change*/
@@ -791,7 +801,6 @@ uint8_t fdc_read(uint16_t addr, void *priv)
void fdc_callback()
{
int temp;
- int doseek = 0;
int drive;
// pclog("fdc_callback %i\n", discint);
@@ -860,102 +869,82 @@ void fdc_callback()
discint = 0;
return;
case 5: /*Write data*/
- if (!fdc.in_seek_mt)
+ readflash_set(READFLASH_FDC, fdc.drive);
+ if (fdc.sector == fdc.params[5])
{
- readflash_set(READFLASH_FDC, fdc.drive);
- fdc.sector++;
- if (fdc.sector > fdc.params[5])
+ fdc.sector = 1;
+ if (fdc.command & 0x80)
{
- fdc.sector = 1;
- if (fdc.command & 0x80)
- {
- fdc.head ^= 1;
- if (!fdc.head)
- {
- fdc.rw_track++;
- doseek = 1;
- }
- }
- else
+ fdc.head ^= 1;
+ if (!fdc.head)
{
fdc.rw_track++;
fdc.tc = 1;
}
}
- if (fdc.tc)
+ else
{
- discint=-2;
- fdc_int();
- fdc.stat=0xD0;
- fdc.res[4]=(fdc.head?4:0)|fdc.drive;
- fdc.res[5]=fdc.res[6]=0;
- fdc.res[7]=fdc.rw_track;
- fdc.res[8]=fdc.head;
- fdc.res[9]=fdc.sector;
- fdc.res[10]=fdc.params[4];
- paramstogo=7;
- return;
- }
- if (doseek)
- {
- fdd_seek(fdc.drive, 1);
- fdc.in_seek_mt = 1;
- /*Allow seek to complete before starting next sector write*/
- return;
+ fdc.rw_track++;
+ fdc.tc = 1;
}
}
- fdc.in_seek_mt = 0;
+ else
+ fdc.sector++;
+ if (fdc.tc)
+ {
+ discint=-2;
+ fdc_int();
+ fdc.stat=0xD0;
+ fdc.res[4]=(fdc.head?4:0)|fdc.drive;
+ fdc.res[5]=fdc.res[6]=0;
+ fdc.res[7]=fdc.rw_track;
+ fdc.res[8]=fdc.head;
+ fdc.res[9]=fdc.sector;
+ fdc.res[10]=fdc.params[4];
+ paramstogo=7;
+ return;
+ }
disc_writesector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]);
// ioc_fiq(IOC_FIQ_DISC_DATA);
return;
case 6: /*Read data*/
// rpclog("Read data %i\n", fdc.tc);
- if (!fdc.in_seek_mt)
+ readflash_set(READFLASH_FDC, fdc.drive);
+ if (fdc.sector == fdc.params[5])
{
- readflash_set(READFLASH_FDC, fdc.drive);
- fdc.sector++;
- if (fdc.sector > fdc.params[5])
+ fdc.sector = 1;
+ if (fdc.command & 0x80)
{
- fdc.sector = 1;
- if (fdc.command & 0x80)
- {
- fdc.head ^= 1;
- if (!fdc.head)
- {
- fdc.rw_track++;
- doseek = 1;
- }
- }
- else
+ fdc.head ^= 1;
+ if (!fdc.head)
{
fdc.rw_track++;
fdc.tc = 1;
}
}
- if (fdc.tc)
+ else
{
- fdc.inread = 0;
- discint=-2;
- fdc_int();
- fdc.stat=0xD0;
- fdc.res[4]=(fdc.head?4:0)|fdc.drive;
- fdc.res[5]=fdc.res[6]=0;
- fdc.res[7]=fdc.rw_track;
- fdc.res[8]=fdc.head;
- fdc.res[9]=fdc.sector;
- fdc.res[10]=fdc.params[4];
- paramstogo=7;
- return;
- }
- if (doseek)
- {
- fdd_seek(fdc.drive, 1);
- fdc.in_seek_mt = 1;
- /*Allow seek to complete before starting next sector read*/
- return;
+ fdc.rw_track++;
+ fdc.tc = 1;
}
}
- fdc.in_seek_mt = 0;
+ else
+ fdc.sector++;
+ if (fdc.tc)
+ {
+ fdc.inread = 0;
+ discint=-2;
+ fdc_int();
+ fdc.stat=0xD0;
+ fdc.res[4]=(fdc.head?4:0)|fdc.drive;
+ fdc.res[5]=fdc.res[6]=0;
+ fdc.res[7]=fdc.rw_track;
+ fdc.res[8]=fdc.head;
+ fdc.res[9]=fdc.sector;
+ fdc.res[10]=fdc.params[4];
+ paramstogo=7;
+ return;
+ }
disc_readsector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]);
fdc.inread = 1;
return;
@@ -1054,14 +1043,16 @@ void fdc_callback()
return;
case 0x0e: /*Dump registers*/
fdc.stat = (fdc.stat & 0xf) | 0xd0;
- fdc.res[3] = fdc.track[0];
- fdc.res[4] = fdc.track[1];
- fdc.res[5] = 0;
- fdc.res[6] = 0;
- fdc.res[7] = fdc.specify[0];
- fdc.res[8] = fdc.specify[1];
- fdc.res[9] = fdc.eot[fdc.drive];
- fdc.res[10] = (fdc.perp & 0x7f) | ((fdc.lock) ? 0x80 : 0);
+ fdc.res[1] = fdc.track[0];
+ fdc.res[2] = fdc.track[1];
+ fdc.res[3] = 0;
+ fdc.res[4] = 0;
+ fdc.res[5] = fdc.specify[0];
+ fdc.res[6] = fdc.specify[1];
+ fdc.res[7] = fdc.eot[fdc.drive];
+ fdc.res[8] = (fdc.perp & 0x7f) | ((fdc.lock) ? 0x80 : 0);
+ fdc.res[9] = fdc.config;
+ fdc.res[10] = fdc.pretrk;
paramstogo=10;
discint=0;
return;
@@ -1206,15 +1197,33 @@ void fdc_finishread()
// rpclog("fdc_finishread\n");
}
-void fdc_notfound()
+void fdc_notfound(int reason)
{
+// pclog("fdc_notfound: reason=%i\n", reason);
timer_disable(&fdc.timer);
fdc_int();
fdc.stat=0xD0;
fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive;
- fdc.res[5]=5;
- fdc.res[6]=0;
+ switch (reason)
+ {
+ case FDC_STATUS_AM_NOT_FOUND:
+ fdc.res[5] = ST1_ND | ST1_MA;
+ fdc.res[6] = 0;
+ break;
+ case FDC_STATUS_NOT_FOUND:
+ fdc.res[5] = ST1_ND;
+ fdc.res[6] = 0;
+ break;
+ case FDC_STATUS_WRONG_CYLINDER:
+ fdc.res[5] = ST1_ND;
+ fdc.res[6] = ST2_WC;
+ break;
+ case FDC_STATUS_BAD_CYLINDER:
+ fdc.res[5] = ST1_ND;
+ fdc.res[6] = ST2_WC | ST2_BC;
+ break;
+ }
fdc.res[7] = fdc.rw_track;
fdc.res[8] = fdc.head;
fdc.res[9] = fdc.sector;
@@ -1389,6 +1398,11 @@ void fdc_discchange_clear(int drive)
disc_changed[drive] = 0;
}
+int fdc_discchange_read()
+{
+ return (disc_changed[fdc.drive] || drive_empty[fdc.drive]) ? 1 : 0;
+}
+
void fdc_set_dskchg_activelow()
{
fdc.dskchg_activelow = 1;
diff --git a/src/fdc.h b/src/fdc.h
index ec198b8..f0aecce 100644
--- a/src/fdc.h
+++ b/src/fdc.h
@@ -7,6 +7,7 @@ void fdc_reset();
void fdc_poll();
void fdc_abort();
void fdc_discchange_clear(int drive);
+int fdc_discchange_read();
void fdc_set_dskchg_activelow();
void fdc_3f1_enable(int enable);
void fdc_set_ps1();
@@ -23,3 +24,13 @@ void fdc_update_boot_drive(int boot_drive);
void fdc_update_densel_polarity(int densel_polarity);
void fdc_update_densel_force(int densel_force);
void fdc_update_drvrate(int drive, int drvrate);
+
+
+
+enum
+{
+ FDC_STATUS_AM_NOT_FOUND,
+ FDC_STATUS_NOT_FOUND,
+ FDC_STATUS_WRONG_CYLINDER,
+ FDC_STATUS_BAD_CYLINDER
+};
diff --git a/src/fdc37c93x.c b/src/fdc37c93x.c
new file mode 100644
index 0000000..890d95d
--- /dev/null
+++ b/src/fdc37c93x.c
@@ -0,0 +1,253 @@
+#include "ibm.h"
+
+#include "fdc.h"
+#include "fdd.h"
+#include "io.h"
+#include "lpt.h"
+#include "serial.h"
+#include "fdc37c93x.h"
+
+typedef struct fdc37c93x_t
+{
+ int index;
+
+ uint8_t global_regs[0x30];
+ uint8_t fdc_regs[0x100];
+ uint8_t ide1_regs[0x100];
+ uint8_t ide2_regs[0x100];
+ uint8_t lpt_regs[0x100];
+ uint8_t com1_regs[0x100];
+ uint8_t com2_regs[0x100];
+ uint8_t rtc_regs[0x100];
+ uint8_t kbd_regs[0x100];
+ uint8_t auxio_regs[0x100];
+ uint8_t accessbus_regs[0x100];
+
+ uint8_t lock[2];
+} fdc37c93x_t;
+
+static fdc37c93x_t fdc37c93x_global;
+
+static void write_lock(fdc37c93x_t *fdc37c93x, uint8_t val)
+{
+ if (val == 0x55 && fdc37c93x->lock[1] == 0x55)
+ fdc_3f1_enable(0);
+ if (fdc37c93x->lock[0] == 0x55 && fdc37c93x->lock[1] == 0x55 && val != 0x55)
+ fdc_3f1_enable(1);
+
+ fdc37c93x->lock[0] = fdc37c93x->lock[1];
+ fdc37c93x->lock[1] = val;
+}
+
+void fdc37c93x_write(uint16_t port, uint8_t val, void *p)
+{
+ fdc37c93x_t *fdc37c93x = (fdc37c93x_t *)p;
+
+// pclog("Write SuperIO %04x %02x\n", port, val);
+ if (fdc37c93x->lock[0] == 0x55 && fdc37c93x->lock[1] == 0x55)
+ {
+ if (port == 0x3f0)
+ {
+ if (val == 0xaa)
+ write_lock(fdc37c93x, val);
+ else
+ fdc37c93x->index = val;
+ }
+ else
+ {
+ uint16_t addr;
+ int irq;
+
+// pclog("fdc37c93x_write: index=%02x dev=%i val=%02x\n", fdc37c93x->index, fdc37c93x->global_regs[7], val);
+ if (fdc37c93x->index < 0x30)
+ {
+ if (fdc37c93x->index != 0x20 && fdc37c93x->index != 0x21)
+ fdc37c93x->global_regs[fdc37c93x->index] = val;
+ }
+ else switch (fdc37c93x->global_regs[7])
+ {
+ case 0:
+ fdc37c93x->fdc_regs[fdc37c93x->index] = val;
+ break;
+ case 1:
+ fdc37c93x->ide1_regs[fdc37c93x->index] = val;
+ break;
+ case 2:
+ fdc37c93x->ide2_regs[fdc37c93x->index] = val;
+ break;
+ case 3:
+ fdc37c93x->lpt_regs[fdc37c93x->index] = val;
+ break;
+ case 4:
+ fdc37c93x->com1_regs[fdc37c93x->index] = val;
+ break;
+ case 5:
+ fdc37c93x->com2_regs[fdc37c93x->index] = val;
+ break;
+ case 6:
+ fdc37c93x->rtc_regs[fdc37c93x->index] = val;
+ break;
+ case 7:
+ fdc37c93x->kbd_regs[fdc37c93x->index] = val;
+ break;
+ case 8:
+ fdc37c93x->auxio_regs[fdc37c93x->index] = val;
+ break;
+ case 9:
+ fdc37c93x->accessbus_regs[fdc37c93x->index] = val;
+ break;
+ }
+
+ fdc_remove();
+ if ((fdc37c93x->global_regs[0x22] & 0x01) && (fdc37c93x->fdc_regs[0x30] & 0x01))
+ {
+// pclog("FDC enabled\n");
+ fdc_add();
+ }
+/* else
+ pclog("FDC disabled\n");*/
+
+ lpt1_remove();
+ lpt2_remove();
+ addr = (fdc37c93x->lpt_regs[0x61] & 0xfc) | ((fdc37c93x->lpt_regs[0x60] & 3) << 8);
+ if ((fdc37c93x->global_regs[0x22] & (1 << 3)) && (fdc37c93x->lpt_regs[0x30] & 0x01))
+ {
+// pclog("LPT addr = %04x\n", addr);
+ lpt1_init(addr);
+ }
+/* else
+ pclog("LPT disabled\n");*/
+
+ serial1_remove();
+ addr = (fdc37c93x->com1_regs[0x61] & 0xf8) | ((fdc37c93x->com1_regs[0x60] & 3) << 8);
+ irq = fdc37c93x->com1_regs[0x70] & 0xf;
+ if ((fdc37c93x->global_regs[0x22] & (1 << 4)) && (fdc37c93x->com1_regs[0x30] & 0x01))
+ {
+// pclog("COM1 addr = %04x, IRQ = %i\n", addr, irq);
+ serial1_set(addr, irq);
+ }
+/* else
+ pclog("COM1 disabled\n");*/
+
+ serial2_remove();
+ addr = (fdc37c93x->com2_regs[0x61] & 0xf8) | ((fdc37c93x->com2_regs[0x60] & 3) << 8);
+ irq = fdc37c93x->com2_regs[0x70] & 0xf;
+ if ((fdc37c93x->global_regs[0x22] & (1 << 5)) && (fdc37c93x->com2_regs[0x30] & 0x01))
+ {
+// pclog("COM2 addr = %04x, IRQ = %i\n", addr, irq);
+ serial2_set(addr, irq);
+ }
+/* else
+ pclog("COM2 disabled\n");*/
+
+
+ fdc_update_enh_mode(fdc37c93x->fdc_regs[0xf0] & 1);
+
+ fdc_update_densel_force((fdc37c93x->fdc_regs[0xf1] & 0x0c) >> 2);
+ fdd_swap = (fdc37c93x->fdc_regs[0xf0] & (1 << 4)) ? 1 : 0;
+ }
+ }
+ else
+ {
+ if (port == 0x3f0)
+ write_lock(fdc37c93x, val);
+ }
+}
+
+uint8_t fdc37c93x_read(uint16_t port, void *p)
+{
+ fdc37c93x_t *fdc37c93x = (fdc37c93x_t *)p;
+
+// pclog("Read SuperIO %04x %02x\n", port, fdc37c665_curreg);
+ if (fdc37c93x->lock[0] == 0x55 && fdc37c93x->lock[1] == 0x55)
+ {
+ if (port == 0x3f1)
+ {
+ if (fdc37c93x->index < 0x30)
+ return fdc37c93x->global_regs[fdc37c93x->index];
+ else switch (fdc37c93x->global_regs[7])
+ {
+ case 0:
+ return fdc37c93x->fdc_regs[fdc37c93x->index];
+ case 1:
+ return fdc37c93x->ide1_regs[fdc37c93x->index];
+ case 2:
+ return fdc37c93x->ide2_regs[fdc37c93x->index];
+ case 3:
+ return fdc37c93x->lpt_regs[fdc37c93x->index];
+ case 4:
+ return fdc37c93x->com1_regs[fdc37c93x->index];
+ case 5:
+ return fdc37c93x->com2_regs[fdc37c93x->index];
+ case 6:
+ return fdc37c93x->rtc_regs[fdc37c93x->index];
+ case 7:
+ return fdc37c93x->kbd_regs[fdc37c93x->index];
+ case 8:
+ return fdc37c93x->auxio_regs[fdc37c93x->index];
+ case 9:
+ return fdc37c93x->accessbus_regs[fdc37c93x->index];
+ }
+ }
+ }
+ return 0xff;
+}
+
+void fdc37c932fr_init()
+{
+ fdc37c93x_t *fdc37c93x = &fdc37c93x_global;
+ int c;
+
+ io_sethandler(0x03f0, 0x0002, fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, fdc37c93x);
+
+ fdc_update_is_nsc(0);
+
+ memset(&fdc37c93x_global, 0, sizeof(fdc37c93x_global));
+
+ fdc37c93x->global_regs[0x03] = 0x03;
+ fdc37c93x->global_regs[0x20] = 0x03;
+ fdc37c93x->global_regs[0x21] = 0x01;
+ fdc37c93x->global_regs[0x24] = 0x04;
+ fdc37c93x->global_regs[0x26] = 0xf0;
+ fdc37c93x->global_regs[0x27] = 0x03;
+
+ fdc37c93x->fdc_regs[0x60] = 0x03;
+ fdc37c93x->fdc_regs[0x61] = 0xf0;
+ fdc37c93x->fdc_regs[0x70] = 0x06;
+ fdc37c93x->fdc_regs[0x74] = 0x02;
+ fdc37c93x->fdc_regs[0xf0] = 0x0e;
+ fdc37c93x->fdc_regs[0xf2] = 0xff;
+
+ fdc37c93x->ide1_regs[0x60] = 0x01;
+ fdc37c93x->ide1_regs[0x61] = 0xf0;
+ fdc37c93x->ide1_regs[0x62] = 0x03;
+ fdc37c93x->ide1_regs[0x63] = 0xf6;
+ fdc37c93x->ide1_regs[0x70] = 0x0e;
+ fdc37c93x->ide1_regs[0xf0] = 0x0c;
+ fdc37c93x->ide1_regs[0xf1] = 0x0d;
+
+ fdc37c93x->lpt_regs[0x74] = 0x04;
+ fdc37c93x->lpt_regs[0xf0] = 0x3c;
+
+ fdc37c93x->com2_regs[0x74] = 0x04;
+ fdc37c93x->com2_regs[0xf1] = 0x02;
+ fdc37c93x->com2_regs[0xf2] = 0x03;
+
+ fdc37c93x->rtc_regs[0x63] = 0x70;
+ fdc37c93x->rtc_regs[0xf4] = 0x03;
+
+ fdc37c93x->auxio_regs[0xb1] = 0x80;
+ fdc37c93x->auxio_regs[0xc0] = 0x01;
+ fdc37c93x->auxio_regs[0xc1] = 0x01;
+ fdc37c93x->auxio_regs[0xc5] = 0x01;
+ fdc37c93x->auxio_regs[0xc6] = 0x01;
+ fdc37c93x->auxio_regs[0xc7] = 0x01;
+ fdc37c93x->auxio_regs[0xc8] = 0x01;
+ fdc37c93x->auxio_regs[0xc9] = 0x80;
+ for (c = 0xcb; c < 0xee; c++)
+ fdc37c93x->auxio_regs[c] = 0x01;
+
+ fdc_update_densel_polarity(1);
+ fdc_update_densel_force(0);
+ fdd_swap = 0;
+}
diff --git a/src/fdc37c93x.h b/src/fdc37c93x.h
new file mode 100644
index 0000000..e661c3d
--- /dev/null
+++ b/src/fdc37c93x.h
@@ -0,0 +1 @@
+extern void fdc37c932fr_init();
diff --git a/src/gameport.c b/src/gameport.c
index d8eb6c4..9b797b4 100644
--- a/src/gameport.c
+++ b/src/gameport.c
@@ -87,15 +87,19 @@ typedef struct gameport_t
static gameport_t *gameport_global = NULL;
-static uint64_t gameport_time(int axis)
+static void gameport_time(gameport_t *gameport, int nr, int axis)
{
if (axis == AXIS_NOT_PRESENT)
- return 0;
-
- axis += 32768;
- axis = (axis * 100) / 65; /*Axis now in ohms*/
- axis = (axis * 11) / 1000;
- return TIMER_USEC * (axis + 24); /*max = 11.115 ms*/
+ {
+ timer_disable(&gameport->axis[nr].timer);
+ }
+ else
+ {
+ axis += 32768;
+ axis = (axis * 100) / 65; /*Axis now in ohms*/
+ axis = (axis * 11) / 1000;
+ timer_set_delay_u64(&gameport->axis[nr].timer, TIMER_USEC * (axis + 24)); /*max = 11.115 ms*/
+ }
}
void gameport_write(uint16_t addr, uint8_t val, void *p)
@@ -104,11 +108,11 @@ void gameport_write(uint16_t addr, uint8_t val, void *p)
gameport->state |= 0x0f;
// pclog("gameport_write : joysticks_present=%i\n", joysticks_present);
-
- timer_set_delay_u64(&gameport->axis[0].timer, gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 0)));
- timer_set_delay_u64(&gameport->axis[1].timer, gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 1)));
- timer_set_delay_u64(&gameport->axis[2].timer, gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 2)));
- timer_set_delay_u64(&gameport->axis[3].timer, gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 3)));
+
+ gameport_time(gameport, 0, gameport->joystick->read_axis(gameport->joystick_dat, 0));
+ gameport_time(gameport, 1, gameport->joystick->read_axis(gameport->joystick_dat, 1));
+ gameport_time(gameport, 2, gameport->joystick->read_axis(gameport->joystick_dat, 2));
+ gameport_time(gameport, 3, gameport->joystick->read_axis(gameport->joystick_dat, 3));
gameport->joystick->write(gameport->joystick_dat);
diff --git a/src/hdd.c b/src/hdd.c
index f2a9fd7..00b246d 100644
--- a/src/hdd.c
+++ b/src/hdd.c
@@ -9,6 +9,7 @@
#include "mfm_xebec.h"
#include "scsi_53c400.h"
#include "scsi_aha1540.h"
+#include "scsi_ibm.h"
#include "xtide.h"
char hdd_controller_name[16];
@@ -39,6 +40,7 @@ static struct
{"[IDE] XTIDE (PS/1)", "xtide_ps1", &xtide_ps1_device, 0, 1, 0},
{"[SCSI] Adaptec AHA-1542C", "aha1542c", &scsi_aha1542c_device, 0, 0, 1},
{"[SCSI] BusLogic BT-545S", "bt545s", &scsi_bt545s_device, 0, 0, 1},
+ {"[SCSI] IBM SCSI Adapter with Cache", "ibmscsi_mca",&scsi_ibm_device, 0, 0, 1},
{"[SCSI] Longshine LCS-6821N", "lcs6821n", &scsi_lcs6821n_device, 0, 0, 1},
{"[SCSI] Rancho RT1000B", "rt1000b", &scsi_rt1000b_device, 0, 0, 1},
{"[SCSI] Trantor T130B", "t130b", &scsi_t130b_device, 0, 0, 1},
diff --git a/src/hdd_esdi.c b/src/hdd_esdi.c
index 6eb239a..04c4317 100644
--- a/src/hdd_esdi.c
+++ b/src/hdd_esdi.c
@@ -917,7 +917,7 @@ static void *esdi_init()
timer_add(&esdi->callback_timer, esdi_callback, esdi, 0);
- mca_add(esdi_mca_read, esdi_mca_write, esdi);
+ mca_add(esdi_mca_read, esdi_mca_write, NULL, esdi);
esdi->pos_regs[0] = 0xff;
esdi->pos_regs[1] = 0xdd;
diff --git a/src/hdd_file.c b/src/hdd_file.c
index 27cba2e..f5c4ffd 100644
--- a/src/hdd_file.c
+++ b/src/hdd_file.c
@@ -5,6 +5,8 @@
#include "ibm.h"
#include "hdd_file.h"
+#include "minivhd/minivhd.h"
+#include "minivhd/minivhd_util.h"
void hdd_load_ext(hdd_file_t *hdd, const char *fn, int spt, int hpc, int tracks, int read_only)
{
@@ -12,17 +14,52 @@ void hdd_load_ext(hdd_file_t *hdd, const char *fn, int spt, int hpc, int tracks,
{
/* Try to open existing hard disk image */
if (read_only)
- hdd->f = fopen64(fn, "rb");
+ hdd->f = (void*)fopen64(fn, "rb");
+ else
+ hdd->f = (void*)fopen64(fn, "rb+");
+ if (hdd->f != NULL)
+ {
+ hdd->img_type = HDD_IMG_RAW;
+ /* Check if the file we opened is a VHD */
+ if (mvhd_file_is_vhd((FILE*)hdd->f))
+ {
+ int err;
+ fclose((FILE*)hdd->f);
+ MVHDMeta *vhdm = mvhd_open(fn, (bool)read_only, &err);
+ if (vhdm == NULL)
+ {
+ hdd->f = NULL;
+ if (err == MVHD_ERR_FILE)
+ {
+ pclog("Cannot open VHD file '%s' : %s",
+ fn, strerror(mvhd_errno));
+ }
+ else
+ {
+ pclog("Cannot open VHD file '%s' : %s",
+ fn, mvhd_strerr(err));
+ }
+ return;
+ }
+ else if (err == MVHD_ERR_TIMESTAMP)
+ {
+ pclog("VHD: Parent/child timestamp mismatch");
+ mvhd_close(vhdm);
+ hdd->f = NULL;
+ return;
+ }
+ hdd->f = (void*)vhdm;
+ hdd->img_type = HDD_IMG_VHD;
+ }
+ }
else
- hdd->f = fopen64(fn, "rb+");
- if (hdd->f == NULL)
{
/* Failed to open existing hard disk image */
if (errno == ENOENT && !read_only)
{
/* Failed because it does not exist,
so try to create new file */
- hdd->f = fopen64(fn, "wb+");
+ hdd->f = (void*)fopen64(fn, "wb+");
if (hdd->f == NULL)
{
pclog("Cannot create file '%s': %s",
@@ -37,13 +74,24 @@ void hdd_load_ext(hdd_file_t *hdd, const char *fn, int spt, int hpc, int tracks,
fn, strerror(errno));
return;
}
+ hdd->img_type = HDD_IMG_RAW;
}
}
-
- hdd->spt = spt;
- hdd->hpc = hpc;
- hdd->tracks = tracks;
- hdd->sectors = spt * hpc * tracks;
+ if (hdd->img_type == HDD_IMG_VHD)
+ {
+ MVHDMeta *vhdm = (MVHDMeta*)hdd->f;
+ MVHDGeom geom = mvhd_get_geometry(vhdm);
+ hdd->spt = geom.spt;
+ hdd->hpc = geom.heads;
+ hdd->tracks = geom.cyl;
+ }
+ else if (hdd->img_type == HDD_IMG_RAW)
+ {
+ hdd->spt = spt;
+ hdd->hpc = hpc;
+ hdd->tracks = tracks;
+ }
+ hdd->sectors = hdd->spt * hdd->hpc * hdd->tracks;
hdd->read_only = read_only;
}
@@ -56,68 +104,99 @@ void hdd_close(hdd_file_t *hdd)
{
if (hdd->f)
{
- fclose(hdd->f);
- hdd->f = NULL;
+ if (hdd->img_type == HDD_IMG_VHD)
+ mvhd_close((MVHDMeta*)hdd->f);
+ else if (hdd->img_type == HDD_IMG_RAW)
+ fclose((FILE*)hdd->f);
}
+ hdd->img_type = HDD_IMG_RAW;
+ hdd->f = NULL;
}
int hdd_read_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer)
{
- off64_t addr;
- int transfer_sectors = nr_sectors;
+ if (hdd->img_type == HDD_IMG_VHD)
+ {
+ return mvhd_read_sectors((MVHDMeta*)hdd->f, offset, nr_sectors, buffer);
+ }
+ else if (hdd->img_type == HDD_IMG_RAW)
+ {
+ off64_t addr;
+ int transfer_sectors = nr_sectors;
- if ((hdd->sectors - offset) < transfer_sectors)
- transfer_sectors = hdd->sectors - offset;
- addr = (uint64_t)offset * 512;
+ if ((hdd->sectors - offset) < transfer_sectors)
+ transfer_sectors = hdd->sectors - offset;
+ addr = (uint64_t)offset * 512;
- fseeko64(hdd->f, addr, SEEK_SET);
- fread(buffer, transfer_sectors*512, 1, hdd->f);
-
- if (nr_sectors != transfer_sectors)
- return 1;
- return 0;
+ fseeko64((FILE*)hdd->f, addr, SEEK_SET);
+ fread(buffer, transfer_sectors*512, 1, (FILE*)hdd->f);
+
+ if (nr_sectors != transfer_sectors)
+ return 1;
+ return 0;
+ }
+ /* Keep the compiler happy */
+ return 1;
}
int hdd_write_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer)
{
- off64_t addr;
- int transfer_sectors = nr_sectors;
-
- if (hdd->read_only)
- return 1;
+ if (hdd->img_type == HDD_IMG_VHD)
+ {
+ return mvhd_write_sectors((MVHDMeta*)hdd->f, offset, nr_sectors, buffer);
+ }
+ else if (hdd->img_type == HDD_IMG_RAW)
+ {
+ off64_t addr;
+ int transfer_sectors = nr_sectors;
- if ((hdd->sectors - offset) < transfer_sectors)
- transfer_sectors = hdd->sectors - offset;
- addr = (uint64_t)offset * 512;
+ if (hdd->read_only)
+ return 1;
- fseeko64(hdd->f, addr, SEEK_SET);
- fwrite(buffer, transfer_sectors*512, 1, hdd->f);
-
- if (nr_sectors != transfer_sectors)
- return 1;
- return 0;
+ if ((hdd->sectors - offset) < transfer_sectors)
+ transfer_sectors = hdd->sectors - offset;
+ addr = (uint64_t)offset * 512;
+
+ fseeko64((FILE*)hdd->f, addr, SEEK_SET);
+ fwrite(buffer, transfer_sectors*512, 1, (FILE*)hdd->f);
+
+ if (nr_sectors != transfer_sectors)
+ return 1;
+ return 0;
+ }
+ /* Keep the compiler happy */
+ return 1;
}
int hdd_format_sectors(hdd_file_t *hdd, int offset, int nr_sectors)
{
- off64_t addr;
- int c;
- uint8_t zero_buffer[512];
- int transfer_sectors = nr_sectors;
-
- if (hdd->read_only)
- return 1;
+ if (hdd->img_type == HDD_IMG_VHD)
+ {
+ return mvhd_format_sectors((MVHDMeta*)hdd->f, offset, nr_sectors);
+ }
+ else if (hdd->img_type == HDD_IMG_RAW)
+ {
+ off64_t addr;
+ int c;
+ uint8_t zero_buffer[512];
+ int transfer_sectors = nr_sectors;
- memset(zero_buffer, 0, 512);
-
- if ((hdd->sectors - offset) < transfer_sectors)
- transfer_sectors = hdd->sectors - offset;
- addr = (uint64_t)offset * 512;
- fseeko64(hdd->f, addr, SEEK_SET);
- for (c = 0; c < transfer_sectors; c++)
- fwrite(zero_buffer, 512, 1, hdd->f);
-
- if (nr_sectors != transfer_sectors)
- return 1;
- return 0;
+ if (hdd->read_only)
+ return 1;
+
+ memset(zero_buffer, 0, 512);
+
+ if ((hdd->sectors - offset) < transfer_sectors)
+ transfer_sectors = hdd->sectors - offset;
+ addr = (uint64_t)offset * 512;
+ fseeko64((FILE*)hdd->f, addr, SEEK_SET);
+ for (c = 0; c < transfer_sectors; c++)
+ fwrite(zero_buffer, 512, 1, (FILE*)hdd->f);
+
+ if (nr_sectors != transfer_sectors)
+ return 1;
+ return 0;
+ }
+ /* Keep the compiler happy */
+ return 1;
}
diff --git a/src/hdd_file.h b/src/hdd_file.h
index e3265e3..485e09f 100644
--- a/src/hdd_file.h
+++ b/src/hdd_file.h
@@ -1,11 +1,18 @@
+typedef enum hdd_img_type
+{
+ HDD_IMG_RAW,
+ HDD_IMG_VHD,
+} hdd_img_type;
+
typedef struct hdd_file_t
{
- FILE *f;
+ void *f;
int spt;
int hpc;
int tracks;
int sectors;
int read_only;
+ hdd_img_type img_type;
} hdd_file_t;
void hdd_load(hdd_file_t *hdd, int d, const char *fn);
diff --git a/src/headland.c b/src/headland.c
index c0ebe01..0208c5d 100644
--- a/src/headland.c
+++ b/src/headland.c
@@ -8,16 +8,173 @@
static int headland_index;
static uint8_t headland_regs[256];
+static uint8_t headland_port_92 = 0xFC, headland_ems_mar = 0, headland_cri = 0;
+static uint8_t headland_regs_cr[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+static uint16_t headland_ems_mr[64];
+
+static mem_mapping_t headland_low_mapping;
+static mem_mapping_t headland_ems_mapping[64];
+static mem_mapping_t headland_mid_mapping;
+static mem_mapping_t headland_high_mapping;
+static mem_mapping_t headland_4000_9FFF_mapping[24];
+
+// TODO - Headland chipset's memory address mapping emulation isn't fully implemented yet, so memory configuration is hardcoded now.
+static int headland_mem_conf_cr0[41] = { 0x00, 0x00, 0x20, 0x40, 0x60, 0xA0, 0x40, 0xE0,
+ 0xA0, 0xC0, 0xE0, 0xE0, 0xC0, 0xE0, 0xE0, 0xE0,
+ 0xE0, 0x20, 0x40, 0x40, 0xA0, 0xC0, 0xE0, 0xE0,
+ 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
+ 0x20, 0x40, 0x60, 0x60, 0xC0, 0xE0, 0xE0, 0xE0,
+ 0xE0 };
+static int headland_mem_conf_cr1[41] = { 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40,
+ 0x00, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x40 };
+
+uint32_t get_headland_addr(uint32_t addr, uint16_t *mr)
+{
+ if (mr && (headland_regs_cr[0] & 2) && (*mr & 0x200))
+ {
+ addr = (addr & 0x3fff) | ((*mr & 0x1F) << 14);
+
+ if(headland_regs_cr[1] & 0x40)
+ {
+ if((headland_regs_cr[4] & 0x80) && (headland_regs_cr[6] & 1))
+ {
+ if(headland_regs_cr[0] & 0x80)
+ {
+ addr |= (*mr & 0x60) << 14;
+ if(*mr & 0x100)
+ addr += ((*mr & 0xC00) << 13) + (((*mr & 0x80) + 0x80) << 15);
+ else
+ addr += (*mr & 0x80) << 14;
+ }
+ else if(*mr & 0x100)
+ addr += ((*mr & 0xC00) << 13) + (((*mr & 0x80) + 0x20) << 15);
+ else
+ addr += (*mr & 0x80) << 12;
+ }
+ else if(headland_regs_cr[0] & 0x80)
+ addr |= (*mr & 0x100) ? ((*mr & 0x80) + 0x400) << 12 : (*mr & 0xE0) << 14;
+ else
+ addr |= (*mr & 0x100) ? ((*mr & 0xE0) + 0x40) << 14 : (*mr & 0x80) << 12;
+ }
+ else
+ {
+ if((headland_regs_cr[4] & 0x80) && (headland_regs_cr[6] & 1))
+ {
+ if(headland_regs_cr[0] & 0x80)
+ {
+ addr |= ((*mr & 0x60) << 14);
+ if(*mr & 0x180)
+ addr += ((*mr & 0xC00) << 13) + (((*mr & 0x180) - 0x60) << 16);
+ }
+ else
+ addr |= ((*mr & 0x60) << 14) | ((*mr & 0x180) << 16) | ((*mr & 0xC00) << 13);
+ }
+ else if(headland_regs_cr[0] & 0x80)
+ addr |= (*mr & 0x1E0) << 14;
+ else
+ addr |= (*mr & 0x180) << 12;
+ }
+ }
+ else if(mr == NULL && (headland_regs_cr[0] & 4) == 0 && mem_size >= 1024 && addr >= 0x100000)
+ addr -= 0x60000;
+
+ return addr;
+}
+
+void headland_set_global_EMS_state(int state)
+{
+ int i;
+ uint32_t base_addr, virt_addr;
+
+ for(i=0; i<32; i++)
+ {
+ base_addr = (i + 16) << 14;
+ if(i >= 24)
+ base_addr += 0x20000;
+ if((state & 2) && (headland_ems_mr[((state & 1) << 5) | i] & 0x200))
+ {
+ virt_addr = get_headland_addr(base_addr, &headland_ems_mr[((state & 1) << 5) | i]);
+ if(i < 24) mem_mapping_disable(&headland_4000_9FFF_mapping[i]);
+ mem_mapping_disable(&headland_ems_mapping[(((state ^ 1) & 1) << 5) | i]);
+ mem_mapping_enable(&headland_ems_mapping[((state & 1) << 5) | i]);
+ if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&headland_ems_mapping[((state & 1) << 5) | i], ram + virt_addr);
+ else mem_mapping_set_exec(&headland_ems_mapping[((state & 1) << 5) | i], NULL);
+ }
+ else
+ {
+ mem_mapping_set_exec(&headland_ems_mapping[((state & 1) << 5) | i], ram + base_addr);
+ mem_mapping_disable(&headland_ems_mapping[(((state ^ 1) & 1) << 5) | i]);
+ mem_mapping_disable(&headland_ems_mapping[((state & 1) << 5) | i]);
+
+ if(i < 24)
+ mem_mapping_enable(&headland_4000_9FFF_mapping[i]);
+ }
+ }
+ flushmmucache();
+}
+
+void headland_memmap_state_update()
+{
+ int i;
+ uint32_t addr;
+
+ for(i=0;i<24;i++)
+ {
+ addr = get_headland_addr(0x40000 + (i << 14), NULL);
+ mem_mapping_set_exec(&headland_4000_9FFF_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL);
+ //pclog("headland_memmap_state_update : Address %06X to %06X\n", 0x40000 + (i << 14), addr);
+ }
+
+ mem_set_mem_state(0xA0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+
+ if (mem_size > 640)
+ {
+ if ((headland_regs_cr[0] & 4) == 0)
+ {
+ mem_mapping_set_addr(&headland_mid_mapping, 0x100000, mem_size > 1024 ? 0x60000 : (mem_size - 640) << 10);
+ mem_mapping_set_exec(&headland_mid_mapping, ram + 0xA0000);
+ if (mem_size > 1024)
+ {
+ mem_mapping_set_addr(&headland_high_mapping, 0x160000, (mem_size - 1024) << 10);
+ mem_mapping_set_exec(&headland_high_mapping, ram + 0x100000);
+ }
+ }
+ else
+ {
+ mem_mapping_set_addr(&headland_mid_mapping, 0xA0000, mem_size > 1024 ? 0x60000 : (mem_size - 640) << 10);
+ mem_mapping_set_exec(&headland_mid_mapping, ram + 0xA0000);
+ if (mem_size > 1024)
+ {
+ mem_mapping_set_addr(&headland_high_mapping, 0x100000, (mem_size - 1024) << 10);
+ mem_mapping_set_exec(&headland_high_mapping, ram + 0x100000);
+ }
+ }
+ }
+
+ headland_set_global_EMS_state(headland_regs_cr[0] & 3);
+}
void headland_write(uint16_t addr, uint8_t val, void *priv)
{
- if (addr & 1)
+ uint8_t old_val, index;
+ uint32_t base_addr, virt_addr;
+
+ switch(addr)
{
- uint8_t old_val = headland_regs[headland_index];
+ case 0x22:
+ headland_index = val;
+ break;
+
+ case 0x23:
+ old_val = headland_regs[headland_index];
if (headland_index == 0xc1 && !is486) val = 0;
headland_regs[headland_index] = val;
- pclog("Headland write %02X %02X\n",headland_index,val);
+ //pclog("Headland write %02X %02X at %04X:%04X\n",headland_index,val,CS,cpu_state.oldpc);
if (headland_index == 0x82)
{
if (val & 0x10)
@@ -30,23 +187,348 @@ void headland_write(uint16_t addr, uint8_t val, void *priv)
if ((val & 1) && !(old_val & 1))
softresetx86();
}
+ break;
+
+ case 0x92:
+ if ((mem_a20_alt ^ val) & 2)
+ {
+ mem_a20_alt = val & 2;
+ mem_a20_recalc();
+ }
+ if ((~headland_port_92 & val) & 1)
+ {
+ softresetx86();
+ cpu_set_edx();
+ }
+ headland_port_92 = val | 0xFC;
+ break;
+
+ case 0x1EC:
+ //pclog("Set EMS Map Register to %02X(actually FF%02X) at %04X:%04X\n", val, val, CS, cpu_state.oldpc);
+ headland_ems_mr[headland_ems_mar & 0x3F] = val | 0xFF00;
+ index = headland_ems_mar & 0x1F;
+ base_addr = (index + 16) << 14;
+ if(index >= 24)
+ base_addr += 0x20000;
+ if((headland_regs_cr[0] & 2) && ((headland_regs_cr[0] & 1) == ((headland_ems_mar & 0x20) >> 5)))
+ {
+ virt_addr = get_headland_addr(base_addr, &headland_ems_mr[headland_ems_mar & 0x3F]);
+ if(index < 24) mem_mapping_disable(&headland_4000_9FFF_mapping[index]);
+ if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&headland_ems_mapping[headland_ems_mar & 0x3F], ram + virt_addr);
+ else mem_mapping_set_exec(&headland_ems_mapping[headland_ems_mar & 0x3F], NULL);
+ mem_mapping_enable(&headland_ems_mapping[headland_ems_mar & 0x3F]);
+ pclog("Map page %d(address %05X) to address %06X\n", index, base_addr, virt_addr);
+ flushmmucache();
+ }
+ if(headland_ems_mar & 0x80) headland_ems_mar++;
+ break;
+
+ case 0x1ED:
+ //pclog("Set Control Register Index to %02X at %04X:%04X\n", val, CS, cpu_state.oldpc);
+ headland_cri = val;
+ break;
+
+ case 0x1EE:
+ //pclog("Set EMS Map Address Register to %02X at %04X:%04X\n", val, CS, cpu_state.oldpc);
+ headland_ems_mar = val;
+ break;
+
+ case 0x1EF:
+ //pclog("Set Control Register %1X to %02X at %04X:%04X\n", headland_cri, val, CS, cpu_state.oldpc);
+ old_val = headland_regs_cr[headland_cri];
+ switch(headland_cri)
+ {
+ case 0:
+ headland_regs_cr[0] = (val & 0x1F) | headland_mem_conf_cr0[(mem_size > 640 ? mem_size : mem_size - 128) >> 9];
+ mem_set_mem_state(0xE0000, 0x10000, (val & 8 ? MEM_READ_INTERNAL : MEM_READ_EXTERNAL) | MEM_WRITE_DISABLED);
+ mem_set_mem_state(0xF0000, 0x10000, (val & 0x10 ? MEM_READ_INTERNAL: MEM_READ_EXTERNAL) | MEM_WRITE_DISABLED);
+ headland_memmap_state_update();
+ break;
+ case 1:
+ headland_regs_cr[1] = (val & 0xBF) | headland_mem_conf_cr1[(mem_size > 640 ? mem_size : mem_size - 128) >> 9];
+ headland_memmap_state_update();
+ break;
+ case 2:
+ case 3:
+ case 5:
+ headland_regs_cr[headland_cri] = val;
+ headland_memmap_state_update();
+ break;
+ case 4:
+ headland_regs_cr[4] = (headland_regs_cr[4] & 0xF0) | (val & 0x0F);
+ if(val & 1)
+ {
+ mem_mapping_disable(&bios_mapping[0]);
+ mem_mapping_disable(&bios_mapping[1]);
+ mem_mapping_disable(&bios_mapping[2]);
+ mem_mapping_disable(&bios_mapping[3]);
+ }
+ else
+ {
+ mem_mapping_enable(&bios_mapping[0]);
+ mem_mapping_enable(&bios_mapping[1]);
+ mem_mapping_enable(&bios_mapping[2]);
+ mem_mapping_enable(&bios_mapping[3]);
+ }
+ break;
+ case 6:
+ if(headland_regs_cr[4] & 0x80)
+ {
+ headland_regs_cr[headland_cri] = (val & 0xFE) | (mem_size > 8192 ? 1 : 0);
+ headland_memmap_state_update();
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void headland_writew(uint16_t addr, uint16_t val, void *priv)
+{
+ uint8_t index;
+ uint32_t base_addr, virt_addr;
+
+ switch(addr)
+ {
+ case 0x1EC:
+ //pclog("Set EMS Map Register to %04X at %04X:%04X\n", val, CS, cpu_state.oldpc);
+ headland_ems_mr[headland_ems_mar & 0x3F] = val;
+ index = headland_ems_mar & 0x1F;
+ base_addr = (index + 16) << 14;
+ if(index >= 24)
+ base_addr += 0x20000;
+ if((headland_regs_cr[0] & 2) && (headland_regs_cr[0] & 1) == ((headland_ems_mar & 0x20) >> 5))
+ {
+ if(val & 0x200)
+ {
+ virt_addr = get_headland_addr(base_addr, &headland_ems_mr[headland_ems_mar & 0x3F]);
+ if(index < 24) mem_mapping_disable(&headland_4000_9FFF_mapping[index]);
+ if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&headland_ems_mapping[headland_ems_mar & 0x3F], ram + virt_addr);
+ else mem_mapping_set_exec(&headland_ems_mapping[headland_ems_mar & 0x3F], NULL);
+ mem_mapping_enable(&headland_ems_mapping[headland_ems_mar & 0x3F]);
+ //pclog("Map page %d(address %05X) to address %07X(val=%04X)\n", index, base_addr, virt_addr, val);
+ }
+ else
+ {
+ mem_mapping_set_exec(&headland_ems_mapping[headland_ems_mar & 0x3F], ram + base_addr);
+ mem_mapping_disable(&headland_ems_mapping[headland_ems_mar & 0x3F]);
+ if(index < 24) mem_mapping_enable(&headland_4000_9FFF_mapping[index]);
+ //pclog("Unmap page %d(address %05X)\n", index, base_addr);
+ }
+ flushmmucache();
+ }
+ if(headland_ems_mar & 0x80) headland_ems_mar++;
+ break;
+
+ default:
+ break;
}
- else
- headland_index = val;
}
uint8_t headland_read(uint16_t addr, void *priv)
{
- if (addr & 1)
+ uint8_t val;
+
+ switch(addr)
{
+ case 0x22:
+ val = headland_index;
+ break;
+
+ case 0x23:
if ((headland_index >= 0xc0 || headland_index == 0x20) && cpu_iscyrix)
- return 0xff; /*Don't conflict with Cyrix config registers*/
- return headland_regs[headland_index];
+ val = 0xff; /*Don't conflict with Cyrix config registers*/
+ else
+ val = headland_regs[headland_index];
+ break;
+
+ case 0x92:
+ val = headland_port_92 | 0xFC;
+ break;
+
+ case 0x1EC:
+ val = headland_ems_mr[headland_ems_mar & 0x3F];
+ if(headland_ems_mar & 0x80) headland_ems_mar++;
+ break;
+
+ case 0x1ED:
+ val = headland_cri;
+ break;
+
+ case 0x1EE:
+ val = headland_ems_mar;
+ break;
+
+ case 0x1EF:
+ switch(headland_cri)
+ {
+ case 0:
+ val = (headland_regs_cr[0] & 0x1F) | headland_mem_conf_cr0[(mem_size > 640 ? mem_size : mem_size - 128) >> 9];
+ break;
+ case 1:
+ val = (headland_regs_cr[1] & 0xBF) | headland_mem_conf_cr1[(mem_size > 640 ? mem_size : mem_size - 128) >> 9];
+ break;
+ case 6:
+ if(headland_regs_cr[4] & 0x80)
+ val = (headland_regs_cr[6] & 0xFE) | (mem_size > 8192 ? 1 : 0);
+ else
+ val = 0;
+ break;
+ default:
+ val = headland_regs_cr[headland_cri];
+ break;
+ }
+ break;
+
+ default:
+ val = 0xFF;
+ break;
}
- return headland_index;
+
+ return val;
+}
+
+uint16_t headland_readw(uint16_t addr, void *priv)
+{
+ uint16_t val;
+
+ switch(addr)
+ {
+ case 0x1EC:
+ val = headland_ems_mr[headland_ems_mar & 0x3F] | ((headland_regs_cr[4] & 0x80) ? 0xF000 : 0xFC00);
+ if(headland_ems_mar & 0x80) headland_ems_mar++;
+ break;
+
+ default:
+ val = 0xFFFF;
+ break;
+ }
+
+ return val;
+}
+
+uint8_t mem_read_headlandb(uint32_t addr, void *priv)
+{
+ uint8_t val = 0xff;
+
+ addr = get_headland_addr(addr, priv);
+ if (addr < (mem_size << 10))
+ val = ram[addr];
+
+ return val;
+}
+
+void mem_write_headlandb(uint32_t addr, uint8_t val, void *priv)
+{
+ addr = get_headland_addr(addr, priv);
+ if (addr < (mem_size << 10))
+ ram[addr] = val;
+}
+
+uint16_t mem_read_headlandw(uint32_t addr, void *priv)
+{
+ uint16_t val = 0xffff;
+
+ if((addr & 0x3FFF) == 0x3FFF) pclog("mem_read_headlandw(%08X, %p) called.\n", addr, priv);
+ addr = get_headland_addr(addr, priv);
+ if (addr < (mem_size << 10))
+ val = *(uint16_t *)&ram[addr];
+
+ return val;
+}
+
+void mem_write_headlandw(uint32_t addr, uint16_t val, void *priv)
+{
+ if((addr & 0x3FFF) == 0x3FFF) pclog("mem_write_headlandw(%08X, %04X, %p) called.\n", addr, val, priv);
+ addr = get_headland_addr(addr, priv);
+ if (addr < (mem_size << 10))
+ *(uint16_t *)&ram[addr] = val;
+}
+
+uint32_t mem_read_headlandl(uint32_t addr, void *priv)
+{
+ uint32_t val = 0xffffffff;
+
+ if((addr & 0x3FFF) > 0x3FFC) pclog("mem_read_headlandl(%08X, %p) called.\n", addr, priv);
+ addr = get_headland_addr(addr, priv);
+ if (addr < (mem_size << 10))
+ val = *(uint32_t *)&ram[addr];
+
+ return val;
+}
+
+void mem_write_headlandl(uint32_t addr, uint32_t val, void *priv)
+{
+ if((addr & 0x3FFF) > 0x3FFC) pclog("mem_write_headland(%08X, %08X, %p) called.\n", addr, val, priv);
+ addr = get_headland_addr(addr, priv);
+ if (addr < (mem_size << 10))
+ *(uint32_t *)&ram[addr] = val;
}
void headland_init()
{
- io_sethandler(0x0022, 0x0002, headland_read, NULL, NULL, headland_write, NULL, NULL, NULL);
+ int i;
+
+ for(i=0; i<8; i++)
+ headland_regs_cr[i] = 0;
+ headland_regs_cr[0] = 4;
+
+ switch(romset)
+ {
+ case ROM_AMI386SX:
+ // Remark - Previously distributed AMI386 BIOS doesn't seem to be for the Headland chipset.
+ io_sethandler(0x0022, 0x0002, headland_read, NULL, NULL, headland_write, NULL, NULL, NULL);
+ break;
+ case ROM_AMA932J:
+ headland_regs_cr[4] = 0x20;
+ io_sethandler(0x0092, 0x0001, headland_read, NULL, NULL, headland_write, NULL, NULL, NULL);
+ break;
+ default:
+ headland_regs_cr[4] = 0;
+ break;
+ }
+
+ io_sethandler(0x01EC, 0x0001, headland_read, headland_readw, NULL, headland_write, headland_writew, NULL, NULL);
+ io_sethandler(0x01ED, 0x0003, headland_read, NULL, NULL, headland_write, NULL, NULL, NULL);
+
+ for(i=0; i<64; i++)
+ headland_ems_mr[i] = 0;
+
+ mem_mapping_disable(&ram_low_mapping);
+ mem_mapping_disable(&ram_mid_mapping);
+ mem_mapping_disable(&ram_high_mapping);
+
+ mem_mapping_add(&headland_low_mapping, 0, 0x40000, mem_read_headlandb, mem_read_headlandw, mem_read_headlandl, mem_write_headlandb, mem_write_headlandw, mem_write_headlandl, ram, MEM_MAPPING_INTERNAL, NULL);
+
+ if(mem_size > 640)
+ {
+ mem_mapping_add(&headland_mid_mapping, 0xA0000, 0x60000, mem_read_headlandb, mem_read_headlandw, mem_read_headlandl, mem_write_headlandb, mem_write_headlandw, mem_write_headlandl, ram + 0xA0000, MEM_MAPPING_INTERNAL, NULL);
+ mem_mapping_enable(&headland_mid_mapping);
+ }
+
+ if(mem_size > 1024)
+ {
+ mem_mapping_add(&headland_high_mapping, 0x100000, ((mem_size - 1024) * 1024), mem_read_headlandb, mem_read_headlandw, mem_read_headlandl, mem_write_headlandb, mem_write_headlandw, mem_write_headlandl, ram + 0x100000, MEM_MAPPING_INTERNAL, NULL);
+ mem_mapping_enable(&headland_high_mapping);
+ }
+
+ for (i = 0; i < 24; i++)
+ {
+ mem_mapping_add(&headland_4000_9FFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_headlandb, mem_read_headlandw, mem_read_headlandl, mem_write_headlandb, mem_write_headlandw, mem_write_headlandl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL);
+ mem_mapping_enable(&headland_4000_9FFF_mapping[i]);
+ }
+
+ for (i = 0; i < 64; i++)
+ {
+ headland_ems_mr[i] = 0;
+ mem_mapping_add(&headland_ems_mapping[i], ((i & 31) + ((i & 31) >= 24 ? 24 : 16)) << 14, 0x04000, mem_read_headlandb, mem_read_headlandw, mem_read_headlandl, mem_write_headlandb, mem_write_headlandw, mem_write_headlandl, ram + (((i & 31) + ((i & 31) >= 24 ? 24 : 16)) << 14), 0, &headland_ems_mr[i]);
+ mem_mapping_disable(&headland_ems_mapping[i]);
+ }
+
+ headland_memmap_state_update();
}
diff --git a/src/i430fx.c b/src/i430fx.c
index 4d328b2..678c824 100644
--- a/src/i430fx.c
+++ b/src/i430fx.c
@@ -106,6 +106,30 @@ void i430fx_write(int func, int addr, uint8_t val, void *priv)
i430fx_map(0xec000, 0x04000, val >> 4);
pclog("i430fx_write : PAM6 write %02X\n", val);
break;
+
+ case 0x72: /*SMRAM*/
+ pclog("Write SMRAM %02x\n", val);
+ val = (val & 0x78) | 2; /*SMRAM always at A0000-BFFFF*/
+ val |= (card_i430fx[0x72] & 0x10); /*D_LCK can not be cleared by software*/
+ if (val & 0x10) /*D_LCK locks D_OPEN and G_SMRAME*/
+ {
+ val &= ~0x48; /*D_OPEN is forced to 0, G_SMRAME is read only*/
+ val |= (card_i430fx[0x72] & 0x08);
+ }
+ if ((card_i430fx[0x72] ^ val) & 0x40)
+ {
+ if (val & 0x40) /*SMRAM enabled*/
+ {
+ pclog("Enable SMRAM\n");
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ }
+ else
+ {
+ pclog("Disable SMRAM\n");
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ }
+ }
+ break;
}
card_i430fx[addr] = val;
@@ -119,21 +143,15 @@ uint8_t i430fx_read(int func, int addr, void *priv)
return card_i430fx[addr];
}
-static uint8_t trc = 0;
-
-void i430fx_trc_write(uint16_t port, uint8_t val, void *p)
+static void i430fx_smram_enable(void)
{
- if ((val & 4) && !(trc & 4))
- {
- if (val & 2) /*Hard reset*/
- {
- i430fx_write(0, 0x59, 0xf, NULL); /*Should reset all PCI devices, but just set PAM0 to point to ROM for now*/
- keyboard_at_reset(); /*Reset keyboard controller to reset system flag*/
- }
- resetx86();
- }
-
- trc = val;
+ if (card_i430fx[0x72] & 8)
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+}
+static void i430fx_smram_disable(void)
+{
+ if (card_i430fx[0x72] & 8)
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
void i430fx_init()
@@ -159,5 +177,11 @@ void i430fx_init()
// card_i430fx[0x74] = 0x0e;
// card_i430fx[0x78] = 0x23;
- io_sethandler(0x0cf9, 0x0001, NULL, NULL, NULL, i430fx_trc_write, NULL, NULL, NULL);
+ smram_enable = i430fx_smram_enable;
+ smram_disable = i430fx_smram_disable;
+}
+
+void i430fx_reset()
+{
+ i430fx_write(0, 0x59, 0xf, NULL); /*Should reset all PCI devices, but just set PAM0 to point to ROM for now*/
}
diff --git a/src/i430fx.h b/src/i430fx.h
index fff11d2..0265f27 100644
--- a/src/i430fx.h
+++ b/src/i430fx.h
@@ -1 +1,2 @@
void i430fx_init();
+void i430fx_reset();
diff --git a/src/i430hx.c b/src/i430hx.c
new file mode 100644
index 0000000..466b002
--- /dev/null
+++ b/src/i430hx.c
@@ -0,0 +1,186 @@
+#include
+
+#include "ibm.h"
+#include "io.h"
+#include "mem.h"
+#include "pci.h"
+
+#include "i430hx.h"
+
+static uint8_t card_i430hx[256];
+
+static void i430hx_map(uint32_t addr, uint32_t size, int state)
+{
+ switch (state & 3)
+ {
+ case 0:
+ mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 1:
+ mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 2:
+ mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ case 3:
+ mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ }
+ flushmmucache_nopc();
+}
+
+void i430hx_write(int func, int addr, uint8_t val, void *priv)
+{
+ if (func)
+ return;
+
+ if (addr >= 0x10 && addr < 0x4f)
+ return;
+
+ switch (addr)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ case 0x0c: case 0x0e:
+ return;
+
+ case 0x04: /*Command register*/
+ val &= 0x02;
+ val |= 0x04;
+ break;
+ case 0x05:
+ val = 0;
+ break;
+
+ case 0x06: /*Status*/
+ val = 0;
+ break;
+ case 0x07:
+ val &= 0x80;
+ val |= 0x02;
+ break;
+
+ case 0x59: /*PAM0*/
+ if ((card_i430hx[0x59] ^ val) & 0xf0)
+ {
+ i430hx_map(0xf0000, 0x10000, val >> 4);
+// shadowbios = (val & 0x10);
+ }
+ pclog("i430hx_write : PAM0 write %02X\n", val);
+ break;
+ case 0x5a: /*PAM1*/
+ if ((card_i430hx[0x5a] ^ val) & 0x0f)
+ i430hx_map(0xc0000, 0x04000, val & 0xf);
+ if ((card_i430hx[0x5a] ^ val) & 0xf0)
+ i430hx_map(0xc4000, 0x04000, val >> 4);
+ break;
+ case 0x5b: /*PAM2*/
+ if ((card_i430hx[0x5b] ^ val) & 0x0f)
+ i430hx_map(0xc8000, 0x04000, val & 0xf);
+ if ((card_i430hx[0x5b] ^ val) & 0xf0)
+ i430hx_map(0xcc000, 0x04000, val >> 4);
+ break;
+ case 0x5c: /*PAM3*/
+ if ((card_i430hx[0x5c] ^ val) & 0x0f)
+ i430hx_map(0xd0000, 0x04000, val & 0xf);
+ if ((card_i430hx[0x5c] ^ val) & 0xf0)
+ i430hx_map(0xd4000, 0x04000, val >> 4);
+ break;
+ case 0x5d: /*PAM4*/
+ if ((card_i430hx[0x5d] ^ val) & 0x0f)
+ i430hx_map(0xd8000, 0x04000, val & 0xf);
+ if ((card_i430hx[0x5d] ^ val) & 0xf0)
+ i430hx_map(0xdc000, 0x04000, val >> 4);
+ break;
+ case 0x5e: /*PAM5*/
+ if ((card_i430hx[0x5e] ^ val) & 0x0f)
+ i430hx_map(0xe0000, 0x04000, val & 0xf);
+ if ((card_i430hx[0x5e] ^ val) & 0xf0)
+ i430hx_map(0xe4000, 0x04000, val >> 4);
+ pclog("i430hx_write : PAM5 write %02X\n", val);
+ break;
+ case 0x5f: /*PAM6*/
+ if ((card_i430hx[0x5f] ^ val) & 0x0f)
+ i430hx_map(0xe8000, 0x04000, val & 0xf);
+ if ((card_i430hx[0x5f] ^ val) & 0xf0)
+ i430hx_map(0xec000, 0x04000, val >> 4);
+ pclog("i430hx_write : PAM6 write %02X\n", val);
+ break;
+
+ case 0x72: /*SMRAM*/
+ pclog("Write SMRAM %02x\n", val);
+ val = (val & 0x78) | 2; /*SMRAM always at A0000-BFFFF*/
+ val |= (card_i430hx[0x72] & 0x10); /*D_LCK can not be cleared by software*/
+ if (val & 0x10) /*D_LCK locks D_OPEN and G_SMRAME*/
+ {
+ val &= ~0x48; /*D_OPEN is forced to 0, G_SMRAME is read only*/
+ val |= (card_i430hx[0x72] & 0x08);
+ }
+ if ((card_i430hx[0x72] ^ val) & 0x40)
+ {
+ if (val & 0x40) /*SMRAM enabled*/
+ {
+ pclog("Enable SMRAM\n");
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ }
+ else
+ {
+ pclog("Disable SMRAM\n");
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ }
+ }
+ break;
+ }
+
+ card_i430hx[addr] = val;
+}
+
+uint8_t i430hx_read(int func, int addr, void *priv)
+{
+ if (func)
+ return 0xff;
+
+ return card_i430hx[addr];
+}
+
+static void i430hx_smram_enable(void)
+{
+ if (card_i430hx[0x72] & 8)
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+}
+static void i430hx_smram_disable(void)
+{
+ if (card_i430hx[0x72] & 8)
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+}
+
+void i430hx_init()
+{
+ pci_add_specific(0, i430hx_read, i430hx_write, NULL);
+
+ memset(card_i430hx, 0, 256);
+ card_i430hx[0x00] = 0x86; card_i430hx[0x01] = 0x80; /*Intel*/
+ card_i430hx[0x02] = 0x50; card_i430hx[0x03] = 0x12; /*82439HX*/
+ card_i430hx[0x04] = 0x06; card_i430hx[0x05] = 0x00;
+ card_i430hx[0x07] = 0x02;
+ card_i430hx[0x08] = 0x00; /*A0 stepping*/
+ card_i430hx[0x0B] = 0x06;
+ card_i430hx[0x51] = 0x20;
+ card_i430hx[0x52] = 0xB5; /*512kb cache*/
+ card_i430hx[0x56] = 0x52; /*DRAM control*/
+ card_i430hx[0x59] = 0x40;
+ card_i430hx[0x5A] = card_i430hx[0x5B] = card_i430hx[0x5C] = card_i430hx[0x5D] = 0x44;
+ card_i430hx[0x5E] = card_i430hx[0x5F] = 0x44;
+ card_i430hx[0x60] = card_i430hx[0x61] = card_i430hx[0x62] = card_i430hx[0x63] = 0x02;
+ card_i430hx[0x64] = card_i430hx[0x5F] = 0x02;
+ card_i430hx[0x65] = card_i430hx[0x66] = card_i430hx[0x67] = 0x02;
+ card_i430hx[0x68] = 0x11;
+
+ smram_enable = i430hx_smram_enable;
+ smram_disable = i430hx_smram_disable;
+}
+
+void i430hx_reset()
+{
+ i430hx_write(0, 0x59, 0xf, NULL); /*Should reset all PCI devices, but just set PAM0 to point to ROM for now*/
+}
diff --git a/src/i430hx.h b/src/i430hx.h
new file mode 100644
index 0000000..30a6685
--- /dev/null
+++ b/src/i430hx.h
@@ -0,0 +1,2 @@
+void i430hx_init();
+void i430hx_reset();
diff --git a/src/i430lx.c b/src/i430lx.c
index 17ef4a9..4d2bb74 100644
--- a/src/i430lx.c
+++ b/src/i430lx.c
@@ -1,10 +1,12 @@
#include
#include "ibm.h"
+#include "ide.h"
#include "io.h"
#include "keyboard_at.h"
#include "mem.h"
#include "pci.h"
+#include "sio.h"
#include "x86.h"
#include "i430lx.h"
@@ -106,6 +108,30 @@ void i430lx_write(int func, int addr, uint8_t val, void *priv)
i430lx_map(0xec000, 0x04000, val >> 4);
pclog("i430lx_write : PAM6 write %02X\n", val);
break;
+
+ case 0x72: /*SMRAM*/
+ pclog("Write SMRAM %02x\n", val);
+ val = (val & 0x38) | 2; /*SMRAM always at A0000-BFFFF*/
+ val |= (card_i430lx[0x72] & 0x08); /*D_LCK can not be cleared by software*/
+ if (val & 0x08) /*D_LCK locks D_OPEN*/
+ {
+ val &= ~0x20; /*D_OPEN is forced to 0*/
+ }
+ val |= (card_i430lx[0x72] & 0x08);
+ if ((card_i430lx[0x72] ^ val) & 0x20)
+ {
+ if (val & 0x20) /*SMRAM enabled*/
+ {
+ pclog("Enable SMRAM\n");
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ }
+ else
+ {
+ pclog("Disable SMRAM\n");
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ }
+ }
+ break;
}
card_i430lx[addr] = val;
@@ -133,14 +159,27 @@ void i430lx_trc_write(uint16_t port, uint8_t val, void *p)
if (val & 2) /*Hard reset*/
{
i430lx_write(0, 0x59, 0xf, NULL); /*Should reset all PCI devices, but just set PAM0 to point to ROM for now*/
+ card_i430lx[0x72] = 0; /*Also clear SMRAM register so BIOS will relocate SMBASE*/
keyboard_at_reset(); /*Reset keyboard controller to reset system flag*/
+ ide_reset_devices();
+ resetx86();
}
- resetx86();
+ else
+ softresetx86();
}
-
+
trc = val;
}
+static void i430lx_smram_enable(void)
+{
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+}
+static void i430lx_smram_disable(void)
+{
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+}
+
void i430lx_init()
{
pci_add_specific(0, i430lx_read, i430lx_write, NULL);
@@ -166,4 +205,7 @@ void i430lx_init()
// card_i430lx[0x78] = 0x23;
io_sethandler(0x0cf9, 0x0001, i430lx_trc_read, NULL, NULL, i430lx_trc_write, NULL, NULL, NULL);
+
+ smram_enable = i430lx_smram_enable;
+ smram_disable = i430lx_smram_disable;
}
diff --git a/src/i430vx.c b/src/i430vx.c
index 79b7517..fde2258 100644
--- a/src/i430vx.c
+++ b/src/i430vx.c
@@ -105,6 +105,30 @@ void i430vx_write(int func, int addr, uint8_t val, void *priv)
i430vx_map(0xec000, 0x04000, val >> 4);
pclog("i430vx_write : PAM6 write %02X\n", val);
break;
+
+ case 0x72: /*SMRAM*/
+ pclog("Write SMRAM %02x\n", val);
+ val = (val & 0x78) | 2; /*SMRAM always at A0000-BFFFF*/
+ val |= (card_i430vx[0x72] & 0x10); /*D_LCK can not be cleared by software*/
+ if (val & 0x10) /*D_LCK locks D_OPEN and G_SMRAME*/
+ {
+ val &= ~0x48; /*D_OPEN is forced to 0, G_SMRAME is read only*/
+ val |= (card_i430vx[0x72] & 0x08);
+ }
+ if ((card_i430vx[0x72] ^ val) & 0x40)
+ {
+ if (val & 0x40) /*SMRAM enabled*/
+ {
+ pclog("Enable SMRAM\n");
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ }
+ else
+ {
+ pclog("Disable SMRAM\n");
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ }
+ }
+ break;
}
card_i430vx[addr] = val;
@@ -118,7 +142,17 @@ uint8_t i430vx_read(int func, int addr, void *priv)
return card_i430vx[addr];
}
-
+static void i430vx_smram_enable(void)
+{
+ if (card_i430vx[0x72] & 8)
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+}
+static void i430vx_smram_disable(void)
+{
+ if (card_i430vx[0x72] & 8)
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+}
+
void i430vx_init()
{
pci_add_specific(0, i430vx_read, i430vx_write, NULL);
@@ -141,4 +175,12 @@ void i430vx_init()
card_i430vx[0x72] = 0x02;
card_i430vx[0x74] = 0x0e;
card_i430vx[0x78] = 0x23;
+
+ smram_enable = i430vx_smram_enable;
+ smram_disable = i430vx_smram_disable;
+}
+
+void i430vx_reset()
+{
+ i430vx_write(0, 0x59, 0xf, NULL); /*Should reset all PCI devices, but just set PAM0 to point to ROM for now*/
}
diff --git a/src/i430vx.h b/src/i430vx.h
index 22bde47..25cda4a 100644
--- a/src/i430vx.h
+++ b/src/i430vx.h
@@ -1 +1,2 @@
void i430vx_init();
+void i430vx_reset();
diff --git a/src/i440bx.c b/src/i440bx.c
new file mode 100644
index 0000000..910f71b
--- /dev/null
+++ b/src/i440bx.c
@@ -0,0 +1,192 @@
+#include
+
+#include "ibm.h"
+#include "io.h"
+#include "keyboard_at.h"
+#include "mem.h"
+#include "pci.h"
+#include "x86.h"
+
+#include "i440bx.h"
+
+static uint8_t card_i440bx[256];
+
+static void i440bx_map(uint32_t addr, uint32_t size, int state)
+{
+ switch (state & 3)
+ {
+ case 0:
+ mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 1:
+ mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 2:
+ mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ case 3:
+ mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ }
+ flushmmucache_nopc();
+}
+
+void i440bx_write(int func, int addr, uint8_t val, void *priv)
+{
+ if (func)
+ return;
+
+ if (addr >= 0x10 && addr < 0x4f)
+ return;
+
+ switch (addr)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ case 0x0c: case 0x0e:
+ return;
+
+ case 0x04: /*Command register*/
+ val &= 0x02;
+ val |= 0x04;
+ break;
+ case 0x05:
+ val = 0;
+ break;
+
+ case 0x06: /*Status*/
+ val = 0;
+ break;
+ case 0x07:
+ val = 0x02;
+ break;
+
+ case 0x59: /*PAM0*/
+ if ((card_i440bx[0x59] ^ val) & 0xf0)
+ {
+ i440bx_map(0xf0000, 0x10000, val >> 4);
+ }
+ pclog("i440bx_write : PAM0 write %02X\n", val);
+// if (val == 0x10)
+// output = 3;
+ break;
+ case 0x5a: /*PAM1*/
+ if ((card_i440bx[0x5a] ^ val) & 0x0f)
+ i440bx_map(0xc0000, 0x04000, val & 0xf);
+ if ((card_i440bx[0x5a] ^ val) & 0xf0)
+ i440bx_map(0xc4000, 0x04000, val >> 4);
+ break;
+ case 0x5b: /*PAM2*/
+ if ((card_i440bx[0x5b] ^ val) & 0x0f)
+ i440bx_map(0xc8000, 0x04000, val & 0xf);
+ if ((card_i440bx[0x5b] ^ val) & 0xf0)
+ i440bx_map(0xcc000, 0x04000, val >> 4);
+ break;
+ case 0x5c: /*PAM3*/
+ if ((card_i440bx[0x5c] ^ val) & 0x0f)
+ i440bx_map(0xd0000, 0x04000, val & 0xf);
+ if ((card_i440bx[0x5c] ^ val) & 0xf0)
+ i440bx_map(0xd4000, 0x04000, val >> 4);
+ break;
+ case 0x5d: /*PAM4*/
+ if ((card_i440bx[0x5d] ^ val) & 0x0f)
+ i440bx_map(0xd8000, 0x04000, val & 0xf);
+ if ((card_i440bx[0x5d] ^ val) & 0xf0)
+ i440bx_map(0xdc000, 0x04000, val >> 4);
+ break;
+ case 0x5e: /*PAM5*/
+ if ((card_i440bx[0x5e] ^ val) & 0x0f)
+ i440bx_map(0xe0000, 0x04000, val & 0xf);
+ if ((card_i440bx[0x5e] ^ val) & 0xf0)
+ i440bx_map(0xe4000, 0x04000, val >> 4);
+ pclog("i440bx_write : PAM5 write %02X\n", val);
+ break;
+ case 0x5f: /*PAM6*/
+ if ((card_i440bx[0x5f] ^ val) & 0x0f)
+ i440bx_map(0xe8000, 0x04000, val & 0xf);
+ if ((card_i440bx[0x5f] ^ val) & 0xf0)
+ i440bx_map(0xec000, 0x04000, val >> 4);
+ pclog("i440bx_write : PAM6 write %02X\n", val);
+ break;
+
+ case 0x72: /*SMRAM*/
+// pclog("Write SMRAM %02x was %02x\n", val,
+ val = (val & 0x78) | 2; /*SMRAM always at A0000-BFFFF*/
+ val |= (card_i440bx[0x72] & 0x10); /*D_LCK can not be cleared by software*/
+ if (val & 0x10) /*D_LCK locks D_OPEN and G_SMRAME*/
+ {
+ val &= ~0x48; /*D_OPEN is forced to 0, G_SMRAME is read only*/
+ val |= (card_i440bx[0x72] & 0x08);
+ }
+ if ((card_i440bx[0x72] ^ val) & 0x40)
+ {
+ if (val & 0x40) /*SMRAM enabled*/
+ {
+ pclog("Enable SMRAM\n");
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ }
+ else
+ {
+ pclog("Disable SMRAM\n");
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ }
+ }
+ break;
+ }
+
+ card_i440bx[addr] = val;
+}
+
+uint8_t i440bx_read(int func, int addr, void *priv)
+{
+ if (func)
+ return 0xff;
+
+ return card_i440bx[addr];
+}
+
+static void i440bx_smram_enable(void)
+{
+// pclog("i440bx_smram_enable: 440BX 0x72=%02x\n", card_i440bx[0x72]);
+ if (card_i440bx[0x72] & 8)
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+}
+static void i440bx_smram_disable(void)
+{
+// pclog("i440bx_smram_disable: 440BX 0x72=%02x\n", card_i440bx[0x72]);
+ if (card_i440bx[0x72] & 8)
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+}
+
+void i440bx_init()
+{
+ pci_add_specific(0, i440bx_read, i440bx_write, NULL);
+
+ memset(card_i440bx, 0, 256);
+ card_i440bx[0x00] = 0x86; card_i440bx[0x01] = 0x80; /*Intel*/
+ card_i440bx[0x02] = 0x92; card_i440bx[0x03] = 0x71; /*82441FX*/
+ card_i440bx[0x04] = 0x06; card_i440bx[0x05] = 0x00;
+ card_i440bx[0x06] = 0x00; card_i440bx[0x07] = 0x02;
+ card_i440bx[0x08] = 0x02; /*B1 stepping*/
+ card_i440bx[0x09] = 0x00; card_i440bx[0x0a] = 0x00; card_i440bx[0x0b] = 0x06;
+ card_i440bx[0x51] = 0x20; /*66 MHz bus*/
+ card_i440bx[0x60] = card_i440bx[0x61] = card_i440bx[0x62] = card_i440bx[0x63] = 0x01;
+ card_i440bx[0x64] = card_i440bx[0x65] = card_i440bx[0x66] = card_i440bx[0x67] = 0x01;
+ card_i440bx[0x72] = 0x02;
+ card_i440bx[0x73] = 0x38;
+ card_i440bx[0x7a] = 0x02; /*AGP disabled*/
+
+ smram_enable = i440bx_smram_enable;
+ smram_disable = i440bx_smram_disable;
+}
+
+void i440bx_reset()
+{
+ i440bx_write(0, 0x59, 0xf, NULL); /*Should reset all PCI devices, but just set PAM0 to point to ROM for now*/
+ i440bx_write(0, 0x5a, 0x0, NULL);
+ i440bx_write(0, 0x5b, 0x0, NULL);
+ i440bx_write(0, 0x5c, 0x0, NULL);
+ i440bx_write(0, 0x5d, 0x0, NULL);
+ i440bx_write(0, 0x5e, 0x0, NULL);
+ i440bx_write(0, 0x5f, 0x0, NULL);
+}
diff --git a/src/i440bx.h b/src/i440bx.h
new file mode 100644
index 0000000..8ed559f
--- /dev/null
+++ b/src/i440bx.h
@@ -0,0 +1,2 @@
+void i440bx_init();
+void i440bx_reset();
diff --git a/src/i440fx.c b/src/i440fx.c
new file mode 100644
index 0000000..87d1dfe
--- /dev/null
+++ b/src/i440fx.c
@@ -0,0 +1,183 @@
+#include
+
+#include "ibm.h"
+#include "io.h"
+#include "keyboard_at.h"
+#include "mem.h"
+#include "pci.h"
+#include "x86.h"
+
+#include "i440fx.h"
+
+static uint8_t card_i440fx[256];
+
+static void i440fx_map(uint32_t addr, uint32_t size, int state)
+{
+ switch (state & 3)
+ {
+ case 0:
+ mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 1:
+ mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 2:
+ mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ case 3:
+ mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ }
+ flushmmucache_nopc();
+}
+
+void i440fx_write(int func, int addr, uint8_t val, void *priv)
+{
+ if (func)
+ return;
+
+ if (addr >= 0x10 && addr < 0x4f)
+ return;
+
+ switch (addr)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ case 0x0c: case 0x0e:
+ return;
+
+ case 0x04: /*Command register*/
+ val &= 0x02;
+ val |= 0x04;
+ break;
+ case 0x05:
+ val = 0;
+ break;
+
+ case 0x06: /*Status*/
+ val = 0;
+ break;
+ case 0x07:
+ val = 0x02;
+ break;
+
+ case 0x59: /*PAM0*/
+ if ((card_i440fx[0x59] ^ val) & 0xf0)
+ {
+ i440fx_map(0xf0000, 0x10000, val >> 4);
+ }
+ pclog("i440fx_write : PAM0 write %02X\n", val);
+ break;
+ case 0x5a: /*PAM1*/
+ if ((card_i440fx[0x5a] ^ val) & 0x0f)
+ i440fx_map(0xc0000, 0x04000, val & 0xf);
+ if ((card_i440fx[0x5a] ^ val) & 0xf0)
+ i440fx_map(0xc4000, 0x04000, val >> 4);
+ break;
+ case 0x5b: /*PAM2*/
+ if ((card_i440fx[0x5b] ^ val) & 0x0f)
+ i440fx_map(0xc8000, 0x04000, val & 0xf);
+ if ((card_i440fx[0x5b] ^ val) & 0xf0)
+ i440fx_map(0xcc000, 0x04000, val >> 4);
+ break;
+ case 0x5c: /*PAM3*/
+ if ((card_i440fx[0x5c] ^ val) & 0x0f)
+ i440fx_map(0xd0000, 0x04000, val & 0xf);
+ if ((card_i440fx[0x5c] ^ val) & 0xf0)
+ i440fx_map(0xd4000, 0x04000, val >> 4);
+ break;
+ case 0x5d: /*PAM4*/
+ if ((card_i440fx[0x5d] ^ val) & 0x0f)
+ i440fx_map(0xd8000, 0x04000, val & 0xf);
+ if ((card_i440fx[0x5d] ^ val) & 0xf0)
+ i440fx_map(0xdc000, 0x04000, val >> 4);
+ break;
+ case 0x5e: /*PAM5*/
+ if ((card_i440fx[0x5e] ^ val) & 0x0f)
+ i440fx_map(0xe0000, 0x04000, val & 0xf);
+ if ((card_i440fx[0x5e] ^ val) & 0xf0)
+ i440fx_map(0xe4000, 0x04000, val >> 4);
+ pclog("i440fx_write : PAM5 write %02X\n", val);
+ break;
+ case 0x5f: /*PAM6*/
+ if ((card_i440fx[0x5f] ^ val) & 0x0f)
+ i440fx_map(0xe8000, 0x04000, val & 0xf);
+ if ((card_i440fx[0x5f] ^ val) & 0xf0)
+ i440fx_map(0xec000, 0x04000, val >> 4);
+ pclog("i440fx_write : PAM6 write %02X\n", val);
+ break;
+
+ case 0x72: /*SMRAM*/
+ pclog("Write SMRAM %02x\n", val);
+ val = (val & 0x78) | 2; /*SMRAM always at A0000-BFFFF*/
+ val |= (card_i440fx[0x72] & 0x10); /*D_LCK can not be cleared by software*/
+ if (val & 0x10) /*D_LCK locks D_OPEN and G_SMRAME*/
+ {
+ val &= ~0x48; /*D_OPEN is forced to 0, G_SMRAME is read only*/
+ val |= (card_i440fx[0x72] & 0x08);
+ }
+ if ((card_i440fx[0x72] ^ val) & 0x40)
+ {
+ if (val & 0x40) /*SMRAM enabled*/
+ {
+ pclog("Enable SMRAM\n");
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ }
+ else
+ {
+ pclog("Disable SMRAM\n");
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ }
+ }
+ break;
+ }
+
+ card_i440fx[addr] = val;
+}
+
+uint8_t i440fx_read(int func, int addr, void *priv)
+{
+ if (func)
+ return 0xff;
+
+ return card_i440fx[addr];
+}
+
+static void i440fx_smram_enable(void)
+{
+ if (card_i440fx[0x72] & 8)
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+}
+static void i440fx_smram_disable(void)
+{
+ if (card_i440fx[0x72] & 8)
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+}
+
+void i440fx_init()
+{
+ pci_add_specific(0, i440fx_read, i440fx_write, NULL);
+
+ memset(card_i440fx, 0, 256);
+ card_i440fx[0x00] = 0x86; card_i440fx[0x01] = 0x80; /*Intel*/
+ card_i440fx[0x02] = 0x37; card_i440fx[0x03] = 0x12; /*82441FX*/
+ card_i440fx[0x04] = 0x06; card_i440fx[0x05] = 0x00;
+ card_i440fx[0x06] = 0x80; card_i440fx[0x07] = 0x02;
+ card_i440fx[0x08] = 0x00; /*A0 stepping*/
+ card_i440fx[0x09] = 0x00; card_i440fx[0x0a] = 0x00; card_i440fx[0x0b] = 0x06;
+ card_i440fx[0x51] = 0x84; /*Uniprocessor, 66 MHz bus*/
+ card_i440fx[0x53] = 0x80;
+ card_i440fx[0x57] = 0x01;
+ card_i440fx[0x58] = 0x10;
+ card_i440fx[0x60] = card_i440fx[0x61] = card_i440fx[0x62] = card_i440fx[0x63] = card_i440fx[0x64] = 0x01;
+ card_i440fx[0x71] = 0x10;
+ card_i440fx[0x72] = 0x02;
+
+ smram_enable = i440fx_smram_enable;
+ smram_disable = i440fx_smram_disable;
+}
+
+void i440fx_reset()
+{
+ i440fx_write(0, 0x59, 0xf, NULL); /*Should reset all PCI devices, but just set PAM0 to point to ROM for now*/
+}
diff --git a/src/i440fx.h b/src/i440fx.h
new file mode 100644
index 0000000..e16eab7
--- /dev/null
+++ b/src/i440fx.h
@@ -0,0 +1,2 @@
+void i440fx_init();
+void i440fx_reset();
diff --git a/src/ibm.h b/src/ibm.h
index ca63e29..c1b6581 100644
--- a/src/ibm.h
+++ b/src/ibm.h
@@ -4,11 +4,21 @@
#include "timer.h"
+
+#ifdef PCEM_BUILD_VERSION
+#define STRINGISE2(string) #string
+#define STRINGISE(string) STRINGISE2(string)
+#define PCEM_VERSION_STRING "build " STRINGISE(PCEM_BUILD_VERSION)
+#else
+#define PCEM_VERSION_STRING "v17"
+#endif
+
#ifdef ABS
#undef ABS
#endif
-#define ABS(x) ((x) > 0 ? (x) : -(x))
+#define ABS(x) ((x) > 0 ? (x) : -(x))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define printf pclog
@@ -95,12 +105,12 @@ typedef struct PIT
int initial[3];
int latched[3];
int disabled[3];
-
+
uint8_t read_status[3];
int do_read_status[3];
-
+
PIT_nr pit_nr[3];
-
+
void (*set_out_funcs[3])(int new_out, int old_out);
} PIT;
@@ -127,7 +137,7 @@ typedef struct dma_t
uint8_t stat, stat_rq;
uint8_t command;
int size;
-
+
uint8_t ps2_mode;
uint8_t arb_level;
uint16_t io_addr;
@@ -165,12 +175,12 @@ int driveempty[2];
#define PCJR (romset == ROM_IBMPCJR)
int GAMEBLASTER, GUS, SSI2001, voodoo_enabled;
-extern int AMSTRAD, AT, is386, PCI, TANDY;
+extern int AMSTRAD, AT, is386, PCI, TANDY, MCA;
enum
{
- ROM_IBMPC = 0, /*301 keyboard error, 131 cassette (!!!) error*/
- ROM_IBMXT, /*301 keyboard error*/
+ ROM_IBMPC = 0,
+ ROM_IBMXT,
ROM_IBMPCJR,
ROM_GENXT, /*'Generic XT BIOS'*/
ROM_DTKXT,
@@ -181,7 +191,7 @@ enum
ROM_PC200,
ROM_PC1640,
ROM_PC2086,
- ROM_PC3086,
+ ROM_PC3086,
ROM_AMIXT, /*XT Clone with AMI BIOS*/
ROM_LTXT,
ROM_LXT3,
@@ -194,21 +204,29 @@ enum
ROM_IBMAT,
ROM_CMDPC30,
ROM_AMI286,
+ ROM_TG286M,
ROM_AWARD286,
+ ROM_GDC212M,
ROM_GW286CT,
ROM_SPC4200P,
ROM_SPC4216P,
+ ROM_SPC4620P,
ROM_DELL200,
ROM_MISC286,
ROM_IBMAT386,
ROM_ACER386,
ROM_KMXC02,
ROM_MEGAPC,
+ ROM_AMA932J,
ROM_AMI386SX,
+ ROM_SPC6000A,
+ ROM_SPC6033P,
ROM_AMI486,
ROM_WIN486,
ROM_PCI486,
ROM_SIS496,
+ ROM_P55VA, /* Epox P55-VA/430VX/Award/SMC FDC37C932FR*/
+ ROM_P55TVP4, /* ASUS P/I-P55TVP4/430VX/Award/Winbond W8387F*/
ROM_430VX,
ROM_ENDEAVOR,
ROM_REVENGE,
@@ -217,6 +235,7 @@ enum
ROM_IBMPS1_2121,
ROM_AMI386DX_OPTI495,
ROM_MR386DX_OPTI495,
+ ROM_P55T2P4, /* ASUS P/I-P55T2P4/430HX/Award/Winbond W8387F*/
ROM_IBMPS2_M30_286,
ROM_IBMPS2_M50,
ROM_IBMPS2_M55SX,
@@ -241,8 +260,23 @@ enum
ROM_XI8088,
ROM_IBMPS2_M70_TYPE3,
ROM_IBMPS2_M70_TYPE4,
+ ROM_TULIP_TC7,
+ ROM_ZD_SUPERS, /* [8088] Zenith Data Systems SupersPort */
+ ROM_PB410A,
+ ROM_PPC512,
+ ROM_BULL_MICRAL_45,
ROM_FIC_VA503P,
-
+ ROM_CBM_SL386SX25,
+ ROM_IBMPS1_2133_451,
+ ROM_ECS_386_32,
+ ROM_LEDGE_MODELM,
+ ROM_HYUNDAI_SUPER286TR,
+ ROM_ITAUTEC_INFOWAYM,
+ ROM_DESKPRO,
+ ROM_VS440FX,
+ ROM_GA686BX,
+ ROM_PC5086,
+
ROM_MAX
};
@@ -260,12 +294,14 @@ enum
GFX_EGA, /*Using IBM EGA BIOS*/
GFX_TVGA, /*Using Trident TVGA8900D BIOS*/
GFX_ET4000, /*Tseng ET4000*/
+ GFX_KASAN16VGA, /*Kasan Hangulmadang-16 (Tseng ET4000AX)*/
+ GFX_TGKOREANVGA, /*Trigem Korean VGA(Tseng ET4000AX)*/
GFX_ET4000W32, /*Tseng ET4000/W32p (Diamond Stealth 32)*/
GFX_BAHAMAS64, /*S3 Vision864 (Paradise Bahamas 64)*/
GFX_N9_9FX, /*S3 764/Trio64 (Number Nine 9FX)*/
GFX_VIRGE, /*S3 Virge*/
GFX_TGUI9440, /*Trident TGUI9440*/
- GFX_VGA, /*IBM VGA*/
+ GFX_VGA, /*IBM VGA*/
GFX_VGAEDGE16, /*ATI VGA Edge-16 (18800-1)*/
GFX_ATIKOREANVGA, /*ATI Korean VGA (28800-5)*/
GFX_VGACHARGER, /*ATI VGA Charger (28800-5)*/
@@ -275,7 +311,7 @@ enum
GFX_VIRGEDX, /*S3 Virge/DX*/
GFX_PHOENIX_TRIO32, /*S3 732/Trio32 (Phoenix)*/
GFX_PHOENIX_TRIO64, /*S3 764/Trio64 (Phoenix)*/
- GFX_INCOLOR, /* Hercules InColor */
+ GFX_INCOLOR, /* Hercules InColor */
GFX_COLORPLUS, /* Plantronics ColorPlus */
GFX_WY700, /* Wyse 700 */
GFX_GENIUS, /* MDSI Genius */
@@ -286,6 +322,20 @@ enum
GFX_CL_GD5434, /*Cirrus Logic CL-GD5434*/
GFX_OTI037, /*Oak OTI-037*/
GFX_COMPAQ_CGA, /*Compaq CGA*/
+ GFX_SIGMA400, /*Sigma Designs Color 400 */
+ GFX_PGC, /*Professional Graphics Controller */
+ GFX_IM1024, /*Vermont Microsystems IM1024 */
+ GFX_EGAWONDER800, /*ATI EGA Wonder 800+*/
+ GFX_MYSTIQUE, /*Matrox Mystique*/
+ GFX_AVGA2, /*Acumos AVGA2 / Cirrus Logic CL-GD5402*/
+ GFX_CL_GD5428, /*Cirrus Logic CL-GD5428*/
+ GFX_IBM_GD5428, /*IBM 1MB SVGA Adapter/A*/
+ GFX_TVGA9000B, /*Trident TVGA9000B*/
+ GFX_BANSHEE, /*Voodoo Banshee - reference PCI board with SGRAM*/
+ GFX_CL_BANSHEE, /*Creative Labs Voodoo Blaster Banshee PCI - with SDRAM*/
+ GFX_VOODOO_3_2000, /*Voodoo 3 2000*/
+ GFX_VOODOO_3_3000, /*Voodoo 3 3000*/
+
GFX_MAX
};
@@ -404,3 +454,5 @@ void saveconfig_global_only();
#define MIN(a, b) ((a) < (b) ? (a) : (b))
void ide_padstr(char *str, const char *src, int len);
+
+void stop_emulation_now(void);
diff --git a/src/ide.c b/src/ide.c
index 4e8d5ef..86a3619 100644
--- a/src/ide.c
+++ b/src/ide.c
@@ -766,7 +766,7 @@ uint16_t readidew(int ide_board)
if (ide->secount)
{
ide_next_sector(ide);
- ide->atastat = BUSY_STAT;
+ ide->atastat = BUSY_STAT | READY_STAT | DSC_STAT;
if (ide->command == WIN_READ_MULTIPLE)
callbackide(ide_board);
else
@@ -824,6 +824,7 @@ void callbackide(int ide_board)
if (ide->type == IDE_NONE)
{
ide->cylinder=0xFFFF;
+ ide->error = 0xff;
atapi->stop();
}
if (IDE_DRIVE_IS_CDROM(ide_other))
@@ -835,6 +836,7 @@ void callbackide(int ide_board)
if (ide_other->type == IDE_NONE)
{
ide_other->cylinder=0xFFFF;
+ ide_other->error = 0xff;
atapi->stop();
}
// pclog("Reset callback\n");
@@ -1271,6 +1273,13 @@ static void *ide_init()
static void ide_close(void *p)
{
+ int c;
+
+ for (c = 0; c < 4; c++)
+ {
+ ide_drives[c].type = IDE_NONE;
+ hdd_close(&ide_drives[c].hdd_file);
+ }
}
void ide_set_bus_master(int (*read_data)(int channel, uint8_t *data, int size, void *p), int (*write_data)(int channel, uint8_t *data, int size, void *p), void (*set_irq)(int channel, void *p), void *p)
@@ -1281,6 +1290,30 @@ void ide_set_bus_master(int (*read_data)(int channel, uint8_t *data, int size, v
ide_bus_master_p = p;
}
+void ide_reset_devices()
+{
+ if (ide_drives[0].type != IDE_NONE || ide_drives[1].type != IDE_NONE)
+ {
+ timer_set_delay_u64(&ide_timer[0], 500*IDE_TIME);
+ ide_drives[0].reset = ide_drives[1].reset = 1;
+ ide_drives[0].atastat = ide_drives[1].atastat = BUSY_STAT;
+ if (ide_drives[0].type != IDE_NONE)
+ cur_ide[0] = 0;
+ else
+ cur_ide[0] = 1;
+ }
+ if (ide_drives[2].type != IDE_NONE || ide_drives[3].type != IDE_NONE)
+ {
+ timer_set_delay_u64(&ide_timer[1], 500*IDE_TIME);
+ ide_drives[2].reset = ide_drives[3].reset = 1;
+ ide_drives[2].atastat = ide_drives[3].atastat = BUSY_STAT;
+ if (ide_drives[2].type != IDE_NONE)
+ cur_ide[1] = 2;
+ else
+ cur_ide[1] = 3;
+ }
+}
+
device_t ide_device =
{
"Standard IDE",
diff --git a/src/ide.h b/src/ide.h
index 0c2ce0b..2ce681a 100644
--- a/src/ide.h
+++ b/src/ide.h
@@ -18,6 +18,7 @@ extern void ide_pri_disable();
extern void ide_sec_disable();
extern void ide_set_bus_master(int (*read_data)(int channel, uint8_t *data, int size, void *p), int (*write_data)(int channel, uint8_t *data, int size, void *p), void (*set_irq)(int channel, void *p), void *p);
void ide_irq_raise(struct IDE *ide);
+void ide_reset_devices();
extern int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size, void *p);
extern int (*ide_bus_master_write_data)(int channel, uint8_t *data, int size, void *p);
diff --git a/src/ide_atapi.c b/src/ide_atapi.c
index 0324e9c..45586e7 100644
--- a/src/ide_atapi.c
+++ b/src/ide_atapi.c
@@ -36,6 +36,7 @@ void atapi_data_write(atapi_device_t *atapi_dev, uint16_t val)
{
atapi_dev->state = ATAPI_STATE_GOT_COMMAND;
timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME);
+ *atapi_dev->atastat = BUSY_STAT | (*atapi_dev->atastat & ERR_STAT);
}
break;
@@ -48,6 +49,7 @@ void atapi_data_write(atapi_device_t *atapi_dev, uint16_t val)
atapi_dev->bus_state = 0;
atapi_dev->state = ATAPI_STATE_WRITE_DATA;
timer_set_delay_u64(&ide_timer[atapi_dev->board], 6 * IDE_TIME);
+ *atapi_dev->atastat = BUSY_STAT | (*atapi_dev->atastat & ERR_STAT);
}
break;
}
@@ -74,6 +76,7 @@ uint16_t atapi_data_read(atapi_device_t *atapi_dev)
{
atapi_dev->state = ATAPI_STATE_NEXT_PHASE;
timer_set_delay_u64(&ide_timer[atapi_dev->board], 6*IDE_TIME);
+ *atapi_dev->atastat = BUSY_STAT | (*atapi_dev->atastat & ERR_STAT);
}
break;
}
diff --git a/src/intel.c b/src/intel.c
index 85ebcbf..3d66644 100644
--- a/src/intel.c
+++ b/src/intel.c
@@ -2,6 +2,7 @@
#include "cpu.h"
#include "io.h"
#include "mem.h"
+#include "model.h"
#include "pit.h"
#include "timer.h"
#include "x86.h"
@@ -64,7 +65,7 @@ static uint8_t batman_timer_read(uint16_t addr, void *p)
{
uint16_t batman_timer_latch;
- cycles -= (int)PITCONST;
+ cycles -= (int)(PITCONST >> 32);
batman_timer_latch = timer_get_remaining_us(&batman_timer);
@@ -87,11 +88,46 @@ void intel_batman_init()
uint8_t endeavor_brdconfig(uint16_t port, void *p)
{
+ uint8_t temp;
+ CPU *cpu_s = &models[model].cpu[cpu_manufacturer].cpus[cpu];
// pclog("endeavor_brdconfig read port=%04x\n", port);
switch (port)
{
case 0x79:
- return 0xff;
+ // Bit # | Description | Bit = 1 | Bit = 0
+ // 0 | Internal CPU Clock Freq. (Switch 6) | 3/2x | 2x (Manual has these swapped in one place?)
+ // 1 | Soft Off capable power supply | No | Yes
+ // 2 | On-board Audio present | Yes | No
+ // 3 | External CPU clock (Switch 7) | |
+ // 4 | External CPU clock (Switch 8) | |
+ // 5 | Setup Disable (Switch 5) | Enable access | Disable access
+ // 6 | Clear CMOS (Switch 4) | Keep values | Clear values
+ // 7 | Password Clear (Switch 3) | Keep password | Clear password
+
+ // Bus Speed | Switch 7 | Switch 8
+ // 50 MHz | Off | Off
+ // 60 Mhz | On | Off
+ // 66 MHz | Off | On
+
+ // Multiplier for each supported processor-
+ // -The 3/2 setting is used for 75 MHz, 90 MHz, and 100 MHz processors
+ // -The 2 times setting is used for 120 MHz processors.
+
+ if (cpu_s->rspeed == 75000000 && cpu_s->pci_speed == 25000000)
+ temp = 0x01;
+ else if (cpu_s->rspeed == 90000000 && cpu_s->pci_speed == 30000000)
+ temp = 0x01 | 0x08;
+ else if (cpu_s->rspeed == 100000000 && cpu_s->pci_speed == 25000000)
+ temp = 0x00;
+ else if (cpu_s->rspeed == 100000000 && cpu_s->pci_speed == 33333333)
+ temp = 0x01 | 0x10;
+ else if (cpu_s->rspeed == 120000000 && cpu_s->pci_speed == 30000000)
+ temp = 0x08;
+ else if (cpu_s->rspeed == 133333333 && cpu_s->pci_speed == 33333333)
+ temp = 0x10;
+ else
+ temp = 0x10; // TODO: how are the overdrive processors configured?
+ return 0xe0 | temp;
}
return 0;
}
@@ -103,11 +139,46 @@ void intel_endeavor_init()
static uint8_t zappa_brdconfig(uint16_t port, void *p)
{
+ uint8_t temp;
+ CPU *cpu_s = &models[model].cpu[cpu_manufacturer].cpus[cpu];
// pclog("zappa_brdconfig read port=%04x\n", port);
switch (port)
{
case 0x79:
- return 0xff;
+ // Bit # | Description | Bit = 1 | Bit = 0
+ // 0 | Internal CPU Clock Freq. (Switch 6) | 3/2x | 2x (Manual has these swapped in one place?)
+ // 1 | No Connect | |
+ // 2 | No Connect | |
+ // 3 | External CPU clock (Switch 7) | |
+ // 4 | External CPU clock (Switch 8) | |
+ // 5 | Setup Disable (Switch 5) | Enable access | Disable access
+ // 6 | Clear CMOS (Switch 4) | Keep values | Clear values
+ // 7 | Password Clear (Switch 3) | Keep password | Clear password
+
+ // Bus Speed | Switch 7 | Switch 8
+ // 50 MHz | Off | Off
+ // 60 Mhz | On | Off
+ // 66 MHz | Off | On
+
+ // Multiplier for each supported processor-
+ // -The 3/2 setting is used for 75 MHz, 90 MHz, and 100 MHz processors
+ // -The 2 times setting is used for 120 MHz processors.
+
+ if (cpu_s->rspeed == 75000000 && cpu_s->pci_speed == 25000000)
+ temp = 0x01;
+ else if (cpu_s->rspeed == 90000000 && cpu_s->pci_speed == 30000000)
+ temp = 0x01 | 0x08;
+ else if (cpu_s->rspeed == 100000000 && cpu_s->pci_speed == 25000000)
+ temp = 0x00;
+ else if (cpu_s->rspeed == 100000000 && cpu_s->pci_speed == 33333333)
+ temp = 0x01 | 0x10;
+ else if (cpu_s->rspeed == 120000000 && cpu_s->pci_speed == 30000000)
+ temp = 0x08;
+ else if (cpu_s->rspeed == 133333333 && cpu_s->pci_speed == 33333333)
+ temp = 0x10;
+ else
+ temp = 0x10; // TODO: how are the overdrive processors configured?
+ return 0xe0 | temp;
}
return 0;
}
diff --git a/src/intel_flash.c b/src/intel_flash.c
index f2de0bb..91ea964 100644
--- a/src/intel_flash.c
+++ b/src/intel_flash.c
@@ -3,6 +3,7 @@
#include "device.h"
#include "mem.h"
+#define FLASH_2MBIT 4
#define FLASH_IS_BXB 2
#define FLASH_INVERT 1
@@ -10,6 +11,7 @@
#define BLOCK_DATA1 1
#define BLOCK_DATA2 2
#define BLOCK_BOOT 3
+#define BLOCK_MAIN2 4 /*2Mbit devices only*/
enum
{
@@ -26,11 +28,13 @@ enum
typedef struct flash_t
{
uint8_t command, status;
- uint8_t flash_id;
+ uint16_t flash_id;
+ uint8_t type;
int invert_high_pin;
- mem_mapping_t mapping[8], mapping_h[8];
- uint32_t block_start[4], block_end[4], block_len[4];
- uint8_t array[131072];
+ mem_mapping_t mapping[8], mapping_h[10];
+ uint32_t block_start[5], block_end[5], block_len[5];
+ uint8_t array[256*1024];
+ uint32_t addr_mask;
} flash_t;
static char flash_path[1024];
@@ -39,13 +43,9 @@ static uint8_t flash_read(uint32_t addr, void *p)
{
flash_t *flash = (flash_t *)p;
if (flash->invert_high_pin)
- {
- // pclog("flash_read : addr=%08x/%08x val=%02x command=%02x %04x:%08x\n", addr, addr ^ 0x10000, flash->array[(addr ^ 0x10000) & 0x1ffff], flash->command, CS, cpu_state.pc);
addr ^= 0x10000;
- if (addr & 0xfff00000) return flash->array[addr & 0x1ffff];
- }
// pclog("flash_read : addr=%08x command=%02x %04x:%08x\n", addr, flash->command, CS, cpu_state.pc);
- addr &= 0x1ffff;
+ addr &= flash->addr_mask;
switch (flash->command)
{
case CMD_READ_ARRAY:
@@ -65,15 +65,26 @@ static uint8_t flash_read(uint32_t addr, void *p)
static uint16_t flash_readw(uint32_t addr, void *p)
{
flash_t *flash = (flash_t *)p;
- addr &= 0x1ffff;
+ addr &= flash->addr_mask;
if (flash->invert_high_pin) addr ^= 0x10000;
- return *(uint16_t *)&(flash->array[addr]);
+ switch (flash->command)
+ {
+ case CMD_READ_ARRAY:
+ default:
+ return *(uint16_t *)&(flash->array[addr]);
+
+ case CMD_IID:
+ return 0x89 | (flash->flash_id << 8);
+
+ case CMD_READ_STATUS:
+ return flash->status;
+ }
}
static uint32_t flash_readl(uint32_t addr, void *p)
{
flash_t *flash = (flash_t *)p;
- addr &= 0x1ffff;
+ addr &= flash->addr_mask;
if (flash->invert_high_pin) addr ^= 0x10000;
return *(uint32_t *)&(flash->array[addr]);
}
@@ -82,14 +93,11 @@ static void flash_write(uint32_t addr, uint8_t val, void *p)
{
flash_t *flash = (flash_t *)p;
int i;
- // pclog("flash_write : addr=%08x val=%02x command=%02x %04x:%08x\n", addr, val, flash->command, CS, cpu_state.pc);
+// pclog("flash_write : addr=%08x val=%02x command=%02x %04x:%08x\n", addr, val, flash->command, CS, cpu_state.pc);
if (flash->invert_high_pin)
- {
addr ^= 0x10000;
- if (addr & 0xfff00000) return;
- }
- addr &= 0x1ffff;
+ addr &= flash->addr_mask;
switch (flash->command)
{
@@ -111,7 +119,7 @@ static void flash_write(uint32_t addr, uint8_t val, void *p)
case CMD_PROGRAM_SETUP:
// pclog("flash_write: program %05x %02x\n", addr, val);
- if ((addr & 0x1e000) != (flash->block_start[3] & 0x1e000))
+ if ((addr & 0x3e000) != (flash->block_start[3] & 0x3e000))
flash->array[addr] = val;
flash->command = CMD_READ_STATUS;
flash->status = 0x80;
@@ -134,9 +142,23 @@ static void intel_flash_add_mappings(flash_t *flash)
for (i = 0; i <= 7; i++)
{
- mem_mapping_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + ((i << 14) & 0x1ffff), MEM_MAPPING_EXTERNAL, (void *)flash);
- mem_mapping_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + ((i << 14) & 0x1ffff), 0, (void *)flash);
+ mem_mapping_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000,
+ flash_read, flash_readw, flash_readl,
+ flash_write, mem_write_nullw, mem_write_nulll,
+ flash->array + (((i << 14) + 0x20000) & flash->addr_mask), MEM_MAPPING_EXTERNAL, (void *)flash);
+ mem_mapping_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000,
+ flash_read, flash_readw, flash_readl,
+ flash_write, mem_write_nullw, mem_write_nulll,
+ flash->array + (((i << 14) + 0x20000) & flash->addr_mask), 0, (void *)flash);
}
+
+ if (flash->type & FLASH_2MBIT)
+ {
+ mem_mapping_add(&flash->mapping_h[8], 0xfffc0000, 0x20000,
+ flash_read, flash_readw, flash_readl,
+ flash_write, mem_write_nullw, mem_write_nulll,
+ flash->array, 0, (void *)flash);
+ }
}
/* This is for boards which invert the high pin - the flash->array pointers need to pointer invertedly in order for INTERNAL writes to go to the right part of the array. */
@@ -146,18 +168,38 @@ static void intel_flash_add_mappings_inverted(flash_t *flash)
for (i = 0; i <= 7; i++)
{
- mem_mapping_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + (((i << 14) ^ 0x10000) & 0x1ffff), MEM_MAPPING_EXTERNAL, (void *)flash);
- mem_mapping_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + (((i << 14) ^ 0x10000) & 0x1ffff), 0, (void *)flash);
+ mem_mapping_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000,
+ flash_read, flash_readw, flash_readl,
+ flash_write, mem_write_nullw, mem_write_nulll,
+ flash->array + ((((i << 14) ^ 0x10000) + 0x20000) & flash->addr_mask), MEM_MAPPING_EXTERNAL, (void *)flash);
+ mem_mapping_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000,
+ flash_read, flash_readw, flash_readl,
+ flash_write, mem_write_nullw, mem_write_nulll,
+ flash->array + ((((i << 14) ^ 0x10000) + 0x20000) & flash->addr_mask), 0, (void *)flash);
}
+
+ if (flash->type & FLASH_2MBIT)
+ {
+ mem_mapping_add(&flash->mapping_h[8], 0xfffc0000, 0x10000,
+ flash_read, flash_readw, flash_readl,
+ flash_write, mem_write_nullw, mem_write_nulll,
+ flash->array + 0x10000, 0, (void *)flash);
+ mem_mapping_add(&flash->mapping_h[9], 0xfffd0000, 0x10000,
+ flash_read, flash_readw, flash_readl,
+ flash_write, mem_write_nullw, mem_write_nulll,
+ flash->array, 0, (void *)flash);
+ }
}
-void *intel_flash_init(uint8_t type)
+void *intel_flash_init(uint8_t type, uint8_t flash_id)
{
FILE *f;
flash_t *flash = malloc(sizeof(flash_t));
memset(flash, 0, sizeof(flash_t));
char fpath[1024];
int i;
+
+ flash->type = type;
switch(romset)
{
@@ -176,45 +218,106 @@ void *intel_flash_init(uint8_t type)
case ROM_ZAPPA:
strcpy(flash_path, "zappa/");
break;
+ case ROM_P55VA:
+ strcpy(flash_path, "p55va/");
+ break;
+ case ROM_P55TVP4:
+ strcpy(flash_path, "p55tvp4/");
+ break;
case ROM_430VX:
strcpy(flash_path, "430vx/");
break;
+ case ROM_P55T2P4:
+ strcpy(flash_path, "p55t2p4/");
+ break;
+ case ROM_ITAUTEC_INFOWAYM:
+ strcpy(flash_path, "infowaym/");
+ break;
+ case ROM_VS440FX:
+ strcpy(flash_path, "vs440fx/");
+ break;
+ case ROM_GA686BX:
+ strcpy(flash_path, "ga686bx/");
+ break;
+
default:
fatal("intel_flash_init on unsupported ROM set %i\n", romset);
}
// pclog("Flash init: Path is: %s\n", flash_path);
- flash->flash_id = (type & FLASH_IS_BXB) ? 0x95 : 0x94;
+ flash->flash_id = flash_id;
+
+ flash->addr_mask = (type & FLASH_2MBIT) ? 0x3ffff : 0x1ffff;
+
+// flash->flash_id = (type & FLASH_IS_BXB) ? 0x95 : 0x94;
flash->invert_high_pin = (type & FLASH_INVERT);
- /* The block lengths are the same both flash types. */
- flash->block_len[BLOCK_MAIN] = 0x1c000;
- flash->block_len[BLOCK_DATA1] = 0x01000;
- flash->block_len[BLOCK_DATA2] = 0x01000;
- flash->block_len[BLOCK_BOOT] = 0x02000;
+ if (type & FLASH_2MBIT)
+ {
+ flash->block_len[BLOCK_MAIN] = 0x20000;
+ flash->block_len[BLOCK_MAIN2] = 0x18000;
+ flash->block_len[BLOCK_DATA1] = 0x02000;
+ flash->block_len[BLOCK_DATA2] = 0x02000;
+ flash->block_len[BLOCK_BOOT] = 0x04000;
- if (type & FLASH_IS_BXB) /* 28F001BX-B */
- {
- flash->block_start[BLOCK_MAIN] = 0x04000; /* MAIN BLOCK */
- flash->block_end[BLOCK_MAIN] = 0x1ffff;
- flash->block_start[BLOCK_DATA1] = 0x03000; /* DATA AREA 1 BLOCK */
- flash->block_end[BLOCK_DATA1] = 0x03fff;
- flash->block_start[BLOCK_DATA2] = 0x04000; /* DATA AREA 2 BLOCK */
- flash->block_end[BLOCK_DATA2] = 0x04fff;
- flash->block_start[BLOCK_BOOT] = 0x00000; /* BOOT BLOCK */
- flash->block_end[BLOCK_BOOT] = 0x01fff;
- }
- else /* 28F001BX-T */
- {
- flash->block_start[BLOCK_MAIN] = 0x00000; /* MAIN BLOCK */
- flash->block_end[BLOCK_MAIN] = 0x1bfff;
- flash->block_start[BLOCK_DATA1] = 0x1c000; /* DATA AREA 1 BLOCK */
- flash->block_end[BLOCK_DATA1] = 0x1cfff;
- flash->block_start[BLOCK_DATA2] = 0x1d000; /* DATA AREA 2 BLOCK */
- flash->block_end[BLOCK_DATA2] = 0x1dfff;
- flash->block_start[BLOCK_BOOT] = 0x1e000; /* BOOT BLOCK */
- flash->block_end[BLOCK_BOOT] = 0x1ffff;
- }
+ if (type & FLASH_IS_BXB) /* 28F001BX-B */
+ {
+ flash->block_start[BLOCK_MAIN] = 0x20000; /* MAIN BLOCK */
+ flash->block_end[BLOCK_MAIN] = 0x3ffff;
+ flash->block_start[BLOCK_MAIN2] = 0x08000; /* MAIN BLOCK */
+ flash->block_end[BLOCK_MAIN2] = 0x1ffff;
+ flash->block_start[BLOCK_DATA1] = 0x04000; /* DATA AREA 1 BLOCK */
+ flash->block_end[BLOCK_DATA1] = 0x05fff;
+ flash->block_start[BLOCK_DATA2] = 0x06000; /* DATA AREA 2 BLOCK */
+ flash->block_end[BLOCK_DATA2] = 0x07fff;
+ flash->block_start[BLOCK_BOOT] = 0x00000; /* BOOT BLOCK */
+ flash->block_end[BLOCK_BOOT] = 0x03fff;
+ }
+ else /* 28F001BX-T */
+ {
+ flash->block_start[BLOCK_MAIN] = 0x00000; /* MAIN BLOCK */
+ flash->block_end[BLOCK_MAIN] = 0x1ffff;
+ flash->block_start[BLOCK_MAIN2] = 0x20000; /* MAIN BLOCK */
+ flash->block_end[BLOCK_MAIN2] = 0x37fff;
+ flash->block_start[BLOCK_DATA1] = 0x38000; /* DATA AREA 1 BLOCK */
+ flash->block_end[BLOCK_DATA1] = 0x39fff;
+ flash->block_start[BLOCK_DATA2] = 0x3a000; /* DATA AREA 2 BLOCK */
+ flash->block_end[BLOCK_DATA2] = 0x3bfff;
+ flash->block_start[BLOCK_BOOT] = 0x3c000; /* BOOT BLOCK */
+ flash->block_end[BLOCK_BOOT] = 0x3ffff;
+ }
+ }
+ else
+ {
+ /* The block lengths are the same both flash types. */
+ flash->block_len[BLOCK_MAIN] = 0x1c000;
+ flash->block_len[BLOCK_DATA1] = 0x01000;
+ flash->block_len[BLOCK_DATA2] = 0x01000;
+ flash->block_len[BLOCK_BOOT] = 0x02000;
+
+ if (type & FLASH_IS_BXB) /* 28F001BX-B */
+ {
+ flash->block_start[BLOCK_MAIN] = 0x04000; /* MAIN BLOCK */
+ flash->block_end[BLOCK_MAIN] = 0x1ffff;
+ flash->block_start[BLOCK_DATA1] = 0x03000; /* DATA AREA 1 BLOCK */
+ flash->block_end[BLOCK_DATA1] = 0x03fff;
+ flash->block_start[BLOCK_DATA2] = 0x04000; /* DATA AREA 2 BLOCK */
+ flash->block_end[BLOCK_DATA2] = 0x04fff;
+ flash->block_start[BLOCK_BOOT] = 0x00000; /* BOOT BLOCK */
+ flash->block_end[BLOCK_BOOT] = 0x01fff;
+ }
+ else /* 28F001BX-T */
+ {
+ flash->block_start[BLOCK_MAIN] = 0x00000; /* MAIN BLOCK */
+ flash->block_end[BLOCK_MAIN] = 0x1bfff;
+ flash->block_start[BLOCK_DATA1] = 0x1c000; /* DATA AREA 1 BLOCK */
+ flash->block_end[BLOCK_DATA1] = 0x1cfff;
+ flash->block_start[BLOCK_DATA2] = 0x1d000; /* DATA AREA 2 BLOCK */
+ flash->block_end[BLOCK_DATA2] = 0x1dfff;
+ flash->block_start[BLOCK_BOOT] = 0x1e000; /* BOOT BLOCK */
+ flash->block_end[BLOCK_BOOT] = 0x1ffff;
+ }
+ }
for (i = 0; i < 8; i++)
{
@@ -226,10 +329,17 @@ void *intel_flash_init(uint8_t type)
{
memcpy(flash->array, rom + 65536, 65536);
memcpy(flash->array + 65536, rom, 65536);
+ if (type & FLASH_2MBIT)
+ {
+ memcpy(flash->array + 0x20000, rom + 0x30000, 65536);
+ memcpy(flash->array + 0x30000, rom + 0x20000, 65536);
+ }
}
else
{
memcpy(flash->array, rom, 131072);
+ if (type & FLASH_2MBIT)
+ memcpy(flash->array + 0x20000, rom + 0x20000, 131072);
}
if (flash->invert_high_pin)
@@ -250,7 +360,9 @@ void *intel_flash_init(uint8_t type)
if (f)
{
fread(&(flash->array[flash->block_start[BLOCK_MAIN]]), flash->block_len[BLOCK_MAIN], 1, f);
- fread(&(flash->array[flash->block_start[BLOCK_DATA1]]), flash->block_len[BLOCK_DATA1], 1, f);
+ if (type & FLASH_2MBIT)
+ fread(&(flash->array[flash->block_start[BLOCK_MAIN2]]), flash->block_len[BLOCK_MAIN2], 1, f);
+ fread(&(flash->array[flash->block_start[BLOCK_DATA1]]), flash->block_len[BLOCK_DATA1], 1, f);
fread(&(flash->array[flash->block_start[BLOCK_DATA2]]), flash->block_len[BLOCK_DATA2], 1, f);
fclose(f);
}
@@ -261,19 +373,29 @@ void *intel_flash_init(uint8_t type)
/* For AMI BIOS'es - Intel 28F001BXT with high address pin inverted. */
void *intel_flash_bxt_ami_init()
{
- return intel_flash_init(FLASH_INVERT);
+ return intel_flash_init(FLASH_INVERT, 0x94);
}
/* For Award BIOS'es - Intel 28F001BXT with high address pin not inverted. */
void *intel_flash_bxt_init()
{
- return intel_flash_init(0);
+ return intel_flash_init(0, 0x94);
}
/* For Acer BIOS'es - Intel 28F001BXB. */
void *intel_flash_bxb_init()
{
- return intel_flash_init(FLASH_IS_BXB);
+ return intel_flash_init(FLASH_IS_BXB, 0x95);
+}
+
+static void *intel_flash_28fb200bxt_init(void)
+{
+ return intel_flash_init(FLASH_INVERT | FLASH_2MBIT, 0x74);
+}
+
+static void *intel_flash_28f002bc_init(void)
+{
+ return intel_flash_init(FLASH_INVERT | FLASH_2MBIT, 0x7c);
}
void intel_flash_close(void *p)
@@ -287,6 +409,8 @@ void intel_flash_close(void *p)
strcat(fpath, "flash.bin");
f = romfopen(fpath, "wb");
fwrite(&(flash->array[flash->block_start[BLOCK_MAIN]]), flash->block_len[BLOCK_MAIN], 1, f);
+ if (flash->type & FLASH_2MBIT)
+ fwrite(&(flash->array[flash->block_start[BLOCK_MAIN2]]), flash->block_len[BLOCK_MAIN2], 1, f);
fwrite(&(flash->array[flash->block_start[BLOCK_DATA1]]), flash->block_len[BLOCK_DATA1], 1, f);
fwrite(&(flash->array[flash->block_start[BLOCK_DATA2]]), flash->block_len[BLOCK_DATA2], 1, f);
fclose(f);
@@ -332,3 +456,29 @@ device_t intel_flash_bxb_device =
NULL,
NULL
};
+
+device_t intel_flash_28fb200bxt_device =
+{
+ "Intel 28FB200BX-T Flash BIOS",
+ 0,
+ intel_flash_28fb200bxt_init,
+ intel_flash_close,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+device_t intel_flash_28f002bc_device =
+{
+ "Intel 28F002BC Flash BIOS",
+ 0,
+ intel_flash_28f002bc_init,
+ intel_flash_close,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
diff --git a/src/intel_flash.h b/src/intel_flash.h
index 2b4cb14..2ea4db5 100644
--- a/src/intel_flash.h
+++ b/src/intel_flash.h
@@ -1,3 +1,5 @@
extern device_t intel_flash_bxt_ami_device;
extern device_t intel_flash_bxt_device;
extern device_t intel_flash_bxb_device;
+extern device_t intel_flash_28fb200bxt_device;
+extern device_t intel_flash_28f002bc_device;
diff --git a/src/io.c b/src/io.c
index 3c6cfd9..ea94c67 100644
--- a/src/io.c
+++ b/src/io.c
@@ -87,36 +87,28 @@ void io_removehandler(uint16_t base, int size,
int c;
for (c = 0; c < size; c++)
{
- if (port_priv[base + c][0] == priv)
+ if (port_priv[base + c][0] == priv &&
+ port_inb[base + c][0] == inb && port_inw[base + c][0] == inw && port_inl[base + c][0] == inl &&
+ port_outb[base + c][0] == outb && port_outw[base + c][0] == outw && port_outl[base + c][0] == outl)
{
- if (port_inb[ base + c][0] == inb)
- port_inb[ base + c][0] = NULL;
- if (port_inw[ base + c][0] == inw)
- port_inw[ base + c][0] = NULL;
- if (port_inl[ base + c][0] == inl)
- port_inl[ base + c][0] = NULL;
- if (port_outb[ base + c][0] == outb)
- port_outb[ base + c][0] = NULL;
- if (port_outw[ base + c][0] == outw)
- port_outw[ base + c][0] = NULL;
- if (port_outl[ base + c][0] == outl)
- port_outl[ base + c][0] = NULL;
+ port_inb[ base + c][0] = NULL;
+ port_inw[ base + c][0] = NULL;
+ port_inl[ base + c][0] = NULL;
+ port_outb[ base + c][0] = NULL;
+ port_outw[ base + c][0] = NULL;
+ port_outl[ base + c][0] = NULL;
port_priv[base + c][0] = NULL;
}
- if (port_priv[base + c][1] == priv)
+ if (port_priv[base + c][1] == priv &&
+ port_inb[base + c][1] == inb && port_inw[base + c][1] == inw && port_inl[base + c][1] == inl &&
+ port_outb[base + c][1] == outb && port_outw[base + c][1] == outw && port_outl[base + c][1] == outl)
{
- if (port_inb[ base + c][1] == inb)
- port_inb[ base + c][1] = NULL;
- if (port_inw[ base + c][1] == inw)
- port_inw[ base + c][1] = NULL;
- if (port_inl[ base + c][1] == inl)
- port_inl[ base + c][1] = NULL;
- if (port_outb[ base + c][1] == outb)
- port_outb[ base + c][1] = NULL;
- if (port_outw[ base + c][1] == outw)
- port_outw[ base + c][1] = NULL;
- if (port_outl[ base + c][1] == outl)
- port_outl[ base + c][1] = NULL;
+ port_inb[ base + c][1] = NULL;
+ port_inw[ base + c][1] = NULL;
+ port_inl[ base + c][1] = NULL;
+ port_outb[base + c][1] = NULL;
+ port_outw[base + c][1] = NULL;
+ port_outl[base + c][1] = NULL;
port_priv[base + c][1] = NULL;
}
}
diff --git a/src/joystick_sw_pad.c b/src/joystick_sw_pad.c
index b5aab34..9bc64dc 100644
--- a/src/joystick_sw_pad.c
+++ b/src/joystick_sw_pad.c
@@ -4,7 +4,7 @@
- Currently alternates between Mode A and Mode B (is there any way of
actually controlling which is used?)
- Windows 9x drivers require Mode B when more than 1 pad connected
- - Packet preceeded by high data (currently 50us), and followed by low
+ - Packet preceeded by high data (currently 40us), and followed by low
data (currently 160us) - timings are probably wrong, but good enough
for everything I've tried
- Analogue inputs are only used to time ID packet request. If A0 timing
@@ -55,7 +55,7 @@ static void sw_timer_over(void *p)
if (sw->poll_left == 1 && !sw->poll_clock)
timer_advance_u64(&sw->poll_timer, TIMER_USEC * 160);
else if (sw->poll_left)
- timer_advance_u64(&sw->poll_timer, TIMER_USEC * 5);
+ timer_set_delay_u64(&sw->poll_timer, TIMER_USEC * 5);
}
static void sw_trigger_timer_over(void *p)
@@ -129,12 +129,10 @@ static void sw_write(void *p)
if (!JOYSTICK_PRESENT(0))
return;
- timer_process();
-
if (!sw->poll_left)
{
sw->poll_clock = 1;
- timer_set_delay_u64(&sw->poll_timer, TIMER_USEC * 50);
+ timer_set_delay_u64(&sw->poll_timer, TIMER_USEC * 40);
if (time_since_last > 9900 && time_since_last < 9940)
{
diff --git a/src/keyboard.c b/src/keyboard.c
index 2d3135f..f41d59f 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -6,243 +6,413 @@ int keybsendcallback = 0;
typedef struct
{
- int scancodes_make[8];
- int scancodes_break[8];
+ uint8_t scancodes_make[8];
+ uint8_t scancodes_break[8];
} scancode;
/*272 = 256 + 16 fake interim scancodes for disambiguation purposes.*/
static scancode scancode_set1[272] =
{
- { {-1}, {-1} }, { {0x01, -1}, {0x81, -1} }, { {0x02, -1}, {0x82, -1} }, { {0x03, -1}, {0x83, -1} },
- { {0x04, -1}, {0x84, -1} }, { {0x05, -1}, {0x85, -1} }, { {0x06, -1}, {0x86, -1} }, { {0x07, -1}, {0x87, -1} },
- { {0x08, -1}, {0x88, -1} }, { {0x09, -1}, {0x89, -1} }, { {0x0a, -1}, {0x8a, -1} }, { {0x0b, -1}, {0x8b, -1} },
- { {0x0c, -1}, {0x8c, -1} }, { {0x0d, -1}, {0x8d, -1} }, { {0x0e, -1}, {0x8e, -1} }, { {0x0f, -1}, {0x8f, -1} },
- { {0x10, -1}, {0x90, -1} }, { {0x11, -1}, {0x91, -1} }, { {0x12, -1}, {0x92, -1} }, { {0x13, -1}, {0x93, -1} },
- { {0x14, -1}, {0x94, -1} }, { {0x15, -1}, {0x95, -1} }, { {0x16, -1}, {0x96, -1} }, { {0x17, -1}, {0x97, -1} },
- { {0x18, -1}, {0x98, -1} }, { {0x19, -1}, {0x99, -1} }, { {0x1a, -1}, {0x9a, -1} }, { {0x1b, -1}, {0x9b, -1} },
- { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, { {0x1e, -1}, {0x9e, -1} }, { {0x1f, -1}, {0x9f, -1} },
- { {0x20, -1}, {0xa0, -1} }, { {0x21, -1}, {0xa1, -1} }, { {0x22, -1}, {0xa2, -1} }, { {0x23, -1}, {0xa3, -1} },
- { {0x24, -1}, {0xa4, -1} }, { {0x25, -1}, {0xa5, -1} }, { {0x26, -1}, {0xa6, -1} }, { {0x27, -1}, {0xa7, -1} },
- { {0x28, -1}, {0xa8, -1} }, { {0x29, -1}, {0xa9, -1} }, { {0x2a, -1}, {0xaa, -1} }, { {0x2b, -1}, {0xab, -1} },
- { {0x2c, -1}, {0xac, -1} }, { {0x2d, -1}, {0xad, -1} }, { {0x2e, -1}, {0xae, -1} }, { {0x2f, -1}, {0xaf, -1} },
- { {0x30, -1}, {0xb0, -1} }, { {0x31, -1}, {0xb1, -1} }, { {0x32, -1}, {0xb2, -1} }, { {0x33, -1}, {0xb3, -1} },
- { {0x34, -1}, {0xb4, -1} }, { {0x35, -1}, {0xb5, -1} }, { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} },
- { {0x38, -1}, {0xb8, -1} }, { {0x39, -1}, {0xb9, -1} }, { {0x3a, -1}, {0xba, -1} }, { {0x3b, -1}, {0xbb, -1} },
- { {0x3c, -1}, {0xbc, -1} }, { {0x3d, -1}, {0xbd, -1} }, { {0x3e, -1}, {0xbe, -1} }, { {0x3f, -1}, {0xbf, -1} },
- { {0x40, -1}, {0xc0, -1} }, { {0x41, -1}, {0xc1, -1} }, { {0x42, -1}, {0xc2, -1} }, { {0x43, -1}, {0xc3, -1} },
- { {0x44, -1}, {0xc4, -1} }, { {0x45, -1}, {0xc5, -1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} },
- { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, { {0x4a, -1}, {0xca, -1} }, { {0x4b, -1}, {0xcb, -1} },
- { {0x4c, -1}, {0xcc, -1} }, { {0x4d, -1}, {0xcd, -1} }, { {0x4e, -1}, {0xce, -1} }, { {0x4f, -1}, {0xcf, -1} },
- { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x53, -1}, {0xd3, -1} },
- { {0x54, -1}, {0xd4, -1} }, { {0x55, -1}, {0xd5, -1} }, { {0x56, -1}, {0xd6, -1} }, { {0x57, -1}, {0xd7, -1} },
- { {0x58, -1}, {0xd8, -1} }, { {0x59, -1}, {0xd9, -1} }, { {0x5a, -1}, {0xda, -1} }, { {0x5b, -1}, {0xdb, -1} },
- { {0x5c, -1}, {0xdc, -1} }, { {0x5d, -1}, {0xdd, -1} }, { {0x5e, -1}, {0xde, -1} }, { {0x5f, -1}, {0xdf, -1} },
- { {0x60, -1}, {0xe0, -1} }, { {0x61, -1}, {0xe1, -1} }, { {0x62, -1}, {0xe2, -1} }, { {0x63, -1}, {0xe3, -1} },
- { {0x64, -1}, {0xe4, -1} }, { {0x65, -1}, {0xe5, -1} }, { {0x66, -1}, {0xe6, -1} }, { {0x67, -1}, {0xe7, -1} },
- { {0x68, -1}, {0xe8, -1} }, { {0x69, -1}, {0xe9, -1} }, { {0x6a, -1}, {0xea, -1} }, { {0x6b, -1}, {0xeb, -1} },
- { {0x6c, -1}, {0xec, -1} }, { {0x6d, -1}, {0xed, -1} }, { {0x6e, -1}, {0xee, -1} }, { {0x6f, -1}, {0xef, -1} },
- { {0x70, -1}, {0xf0, -1} }, { {0x71, -1}, {0xf1, -1} }, { {0x72, -1}, {0xf2, -1} }, { {0x73, -1}, {0xf3, -1} },
- { {0x74, -1}, {0xf4, -1} }, { {0x75, -1}, {0xf5, -1} }, { {0x76, -1}, {0xf6, -1} }, { {0x77, -1}, {0xf7, -1} },
- { {0x78, -1}, {0xf8, -1} }, { {0x79, -1}, {0xf9, -1} }, { {0x7a, -1}, {0xfa, -1} }, { {0x7b, -1}, {0xfb, -1} },
- { {0x7c, -1}, {0xfc, -1} }, { {0x7d, -1}, {0xfd, -1} }, { {0x7e, -1}, {0xfe, -1} }, { {0x7f, -1}, {0xff, -1} },
+ { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} },
+ { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, { {0x06, 0}, {0x86, 0} }, { {0x07, 0}, {0x87, 0} },
+ { {0x08, 0}, {0x88, 0} }, { {0x09, 0}, {0x89, 0} }, { {0x0a, 0}, {0x8a, 0} }, { {0x0b, 0}, {0x8b, 0} },
+ { {0x0c, 0}, {0x8c, 0} }, { {0x0d, 0}, {0x8d, 0} }, { {0x0e, 0}, {0x8e, 0} }, { {0x0f, 0}, {0x8f, 0} },
+ { {0x10, 0}, {0x90, 0} }, { {0x11, 0}, {0x91, 0} }, { {0x12, 0}, {0x92, 0} }, { {0x13, 0}, {0x93, 0} },
+ { {0x14, 0}, {0x94, 0} }, { {0x15, 0}, {0x95, 0} }, { {0x16, 0}, {0x96, 0} }, { {0x17, 0}, {0x97, 0} },
+ { {0x18, 0}, {0x98, 0} }, { {0x19, 0}, {0x99, 0} }, { {0x1a, 0}, {0x9a, 0} }, { {0x1b, 0}, {0x9b, 0} },
+ { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, { {0x1e, 0}, {0x9e, 0} }, { {0x1f, 0}, {0x9f, 0} },
+ { {0x20, 0}, {0xa0, 0} }, { {0x21, 0}, {0xa1, 0} }, { {0x22, 0}, {0xa2, 0} }, { {0x23, 0}, {0xa3, 0} },
+ { {0x24, 0}, {0xa4, 0} }, { {0x25, 0}, {0xa5, 0} }, { {0x26, 0}, {0xa6, 0} }, { {0x27, 0}, {0xa7, 0} },
+ { {0x28, 0}, {0xa8, 0} }, { {0x29, 0}, {0xa9, 0} }, { {0x2a, 0}, {0xaa, 0} }, { {0x2b, 0}, {0xab, 0} },
+ { {0x2c, 0}, {0xac, 0} }, { {0x2d, 0}, {0xad, 0} }, { {0x2e, 0}, {0xae, 0} }, { {0x2f, 0}, {0xaf, 0} },
+ { {0x30, 0}, {0xb0, 0} }, { {0x31, 0}, {0xb1, 0} }, { {0x32, 0}, {0xb2, 0} }, { {0x33, 0}, {0xb3, 0} },
+ { {0x34, 0}, {0xb4, 0} }, { {0x35, 0}, {0xb5, 0} }, { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} },
+ { {0x38, 0}, {0xb8, 0} }, { {0x39, 0}, {0xb9, 0} }, { {0x3a, 0}, {0xba, 0} }, { {0x3b, 0}, {0xbb, 0} },
+ { {0x3c, 0}, {0xbc, 0} }, { {0x3d, 0}, {0xbd, 0} }, { {0x3e, 0}, {0xbe, 0} }, { {0x3f, 0}, {0xbf, 0} },
+ { {0x40, 0}, {0xc0, 0} }, { {0x41, 0}, {0xc1, 0} }, { {0x42, 0}, {0xc2, 0} }, { {0x43, 0}, {0xc3, 0} },
+ { {0x44, 0}, {0xc4, 0} }, { {0x45, 0}, {0xc5, 0} }, { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} },
+ { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, { {0x4a, 0}, {0xca, 0} }, { {0x4b, 0}, {0xcb, 0} },
+ { {0x4c, 0}, {0xcc, 0} }, { {0x4d, 0}, {0xcd, 0} }, { {0x4e, 0}, {0xce, 0} }, { {0x4f, 0}, {0xcf, 0} },
+ { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} },
+ { {0x54, 0}, {0xd4, 0} }, { {0x55, 0}, {0xd5, 0} }, { {0x56, 0}, {0xd6, 0} }, { {0x57, 0}, {0xd7, 0} },
+ { {0x58, 0}, {0xd8, 0} }, { {0x59, 0}, {0xd9, 0} }, { {0x5a, 0}, {0xda, 0} }, { {0x5b, 0}, {0xdb, 0} },
+ { {0x5c, 0}, {0xdc, 0} }, { {0x5d, 0}, {0xdd, 0} }, { {0x5e, 0}, {0xde, 0} }, { {0x5f, 0}, {0xdf, 0} },
+ { {0x60, 0}, {0xe0, 0} }, { {0x61, 0}, {0xe1, 0} }, { {0x62, 0}, {0xe2, 0} }, { {0x63, 0}, {0xe3, 0} },
+ { {0x64, 0}, {0xe4, 0} }, { {0x65, 0}, {0xe5, 0} }, { {0x66, 0}, {0xe6, 0} }, { {0x67, 0}, {0xe7, 0} },
+ { {0x68, 0}, {0xe8, 0} }, { {0x69, 0}, {0xe9, 0} }, { {0x6a, 0}, {0xea, 0} }, { {0x6b, 0}, {0xeb, 0} },
+ { {0x6c, 0}, {0xec, 0} }, { {0x6d, 0}, {0xed, 0} }, { {0x6e, 0}, {0xee, 0} }, { {0x6f, 0}, {0xef, 0} },
+ { {0x70, 0}, {0xf0, 0} }, { {0x71, 0}, {0xf1, 0} }, { {0x72, 0}, {0xf2, 0} }, { {0x73, 0}, {0xf3, 0} },
+ { {0x74, 0}, {0xf4, 0} }, { {0x75, 0}, {0xf5, 0} }, { {0x76, 0}, {0xf6, 0} }, { {0x77, 0}, {0xf7, 0} },
+ { {0x78, 0}, {0xf8, 0} }, { {0x79, 0}, {0xf9, 0} }, { {0x7a, 0}, {0xfa, 0} }, { {0x7b, 0}, {0xfb, 0} },
+ { {0x7c, 0}, {0xfc, 0} }, { {0x7d, 0}, {0xfd, 0} }, { {0x7e, 0}, {0xfe, 0} }, { {0x7f, 0}, {0xff, 0} },
- { {0x80, -1}, {-1} }, { {0x81, -1}, {-1} }, { {0x82, -1}, {-1} }, { {0xe0, 0x03, -1}, {0xe0, 0x83, -1} }, /*80*/
- { {0xe0, 0x04, -1}, {0xe0, 0x84, -1} }, { {0x85, -1}, {-1} }, { {0x86, -1}, {-1} }, { {0x87, -1}, {-1} }, /*84*/
- { {0xe0, 0x08, -1}, {0xe0, 0x88, -1} }, { {0xe0, 0x09, -1}, {0xe0, 0x89, -1} }, { {0xe0, 0x0a, -1}, {0xe0, 0x8a, -1} }, { {0xe0, 0x0b, -1}, {0xe0, 0x8b, -1} }, /*88*/
- { {0xe0, 0x0c, -1}, {0xe0, 0x8c, -1} }, { {-1}, {-1} }, { {0xe0, 0x0e, -1}, {0xe0, 0x8e, -1} }, { {0xe0, 0x0f, -1}, {0xe0, 0x8f, -1} }, /*8c*/
- { {0xe0, 0x10, -1}, {0xe0, 0x90, -1} }, { {0xe0, 0x11, -1}, {0xe0, 0x91, -1} }, { {0xe0, 0x12, -1}, {0xe0, 0x92, -1} }, { {0xe0, 0x13, -1}, {0xe0, 0x93, -1} }, /*90*/
- { {0xe0, 0x14, -1}, {0xe0, 0x94, -1} }, { {0xe0, 0x15, -1}, {0xe0, 0x95, -1} }, { {0xe0, 0x16, -1}, {0xe0, 0x96, -1} }, { {0xe0, 0x17, -1}, {0xe0, 0x97, -1} }, /*94*/
- { {0xe0, 0x18, -1}, {0xe0, 0x98, -1} }, { {0xe0, 0x19, -1}, {0xe0, 0x99, -1} }, { {0xe0, 0x1a, -1}, {0xe0, 0x9a, -1} }, { {0xe0, 0x1b, -1}, {0xe0, 0x9b, -1} }, /*98*/
- { {0xe0, 0x1c, -1}, {0xe0, 0x9c, -1} }, { {0xe0, 0x1d, -1}, {0xe0, 0x9d, -1} }, { {0xe0, 0x1e, -1}, {0xe0, 0x9e, -1} }, { {0xe0, 0x1f, -1}, {0xe0, 0x9f, -1} }, /*9c*/
- { {0xe0, 0x20, -1}, {0xe0, 0xa0, -1} }, { {0xe0, 0x21, -1}, {0xe0, 0xa1, -1} }, { {0xe0, 0x22, -1}, {0xe0, 0xa2, -1} }, { {0xe0, 0x23, -1}, {0xe0, 0xa3, -1} }, /*a0*/
- { {0xe0, 0x24, -1}, {0xe0, 0xa4, -1} }, { {0xe0, 0x25, -1}, {0xe0, 0xa5, -1} }, { {0xe0, 0x26, -1}, {0xe0, 0xa6, -1} }, { {-1}, {-1} }, /*a4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {0xe0, 0x2a, -1}, {0xe0, 0xaa, -1} }, { {-1}, {-1} }, /*a8*/
- { {0xe0, 0x2c, -1}, {0xe0, 0xac, -1} }, { {0xe0, 0x2d, -1}, {0xe0, 0xad, -1} }, { {0xe0, 0x2e, -1}, {0xe0, 0xae, -1} }, { {0xe0, 0x2f, -1}, {0xe0, 0xaf, -1} }, /*ac*/
- { {0xe0, 0x30, -1}, {0xe0, 0xb0, -1} }, { {0xe0, 0x31, -1}, {0xe0, 0xb1, -1} }, { {0xe0, 0x32, -1}, {0xe0, 0xb2, -1} }, { {-1}, {-1} }, /*b0*/
- { {0xe0, 0x34, -1}, {0xe0, 0xb4, -1} }, { {0xe0, 0x35, -1}, {0xe0, 0xb5, -1} }, { {0xe0, 0x36, -1}, {0xe0, 0xb6, -1} }, { {0xe0, 0x37, -1}, {0xe0, 0xb7, -1} }, /*b4*/
- { {0xe0, 0x38, -1}, {0xe0, 0xb8, -1} }, { {-1}, {-1} }, { {0xe0, 0x3a, -1}, {0xe0, 0xba, -1} }, { {0xe0, 0x3b, -1}, {0xe0, 0xbb, -1} }, /*b8*/
- { {0xe0, 0x3c, -1}, {0xe0, 0xbc, -1} }, { {0xe0, 0x3d, -1}, {0xe0, 0xbd, -1} }, { {0xe0, 0x3e, -1}, {0xe0, 0xbe, -1} }, { {0xe0, 0x3f, -1}, {0xe0, 0xbf, -1} }, /*bc*/
- { {0xe0, 0x40, -1}, {0xe0, 0xc0, -1} }, { {0xe0, 0x41, -1}, {0xe0, 0xc1, -1} }, { {0xe0, 0x42, -1}, {0xe0, 0xc2, -1} }, { {0xe0, 0x43, -1}, {0xe0, 0xc3, -1} }, /*c0*/
- { {0xe0, 0x44, -1}, {0xe0, 0xc4, -1} }, { {-1}, {-1} }, { {0xe0, 0x46, -1}, {0xe0, 0xc6, -1} }, { {0xe0, 0x47, -1}, {0xe0, 0xc7, -1} }, /*c4*/
- { {0xe0, 0x48, -1}, {0xe0, 0xc8, -1} }, { {0xe0, 0x49, -1}, {0xe0, 0xc9, -1} }, { {-1}, {-1} }, { {0xe0, 0x4b, -1}, {0xe0, 0xcb, -1} }, /*c8*/
- { {0xe0, 0x4c, -1}, {0xe0, 0xcc, -1} }, { {0xe0, 0x4d, -1}, {0xe0, 0xcd, -1} }, { {0xe0, 0x4e, -1}, {0xe0, 0xce, -1} }, { {0xe0, 0x4f, -1}, {0xe0, 0xcf, -1} }, /*cc*/
- { {0xe0, 0x50, -1}, {0xe0, 0xd0, -1} }, { {0xe0, 0x51, -1}, {0xe0, 0xd1, -1} }, { {0xe0, 0x52, -1}, {0xe0, 0xd2, -1} }, { {0xe0, 0x53, -1}, {0xe0, 0xd3, -1} }, /*d0*/
- { {0xd4, -1}, {-1} }, { {0xe0, 0x55, -1}, {0xe0, 0xd5, -1} }, { {-1}, {-1} }, { {0xe0, 0x57, -1}, {0xe0, 0xd7, -1} }, /*d4*/
- { {0xe0, 0x58, -1}, {0xe0, 0xd8, -1} }, { {0xe0, 0x59, -1}, {0xe0, 0xd9, -1} }, { {0xe0, 0x5a, -1}, {0xe0, 0xaa, -1} }, { {0xe0, 0x5b, -1}, {0xe0, 0xdb, -1} }, /*d8*/
- { {0xe0, 0x5c, -1}, {0xe0, 0xdc, -1} }, { {0xe0, 0x5d, -1}, {0xe0, 0xdd, -1} }, { {0xe0, 0x5e, -1}, {0xe0, 0xee, -1} }, { {0xe0, 0x5f, -1}, {0xe0, 0xdf, -1} }, /*dc*/
- { {-1}, {-1} }, { {0xe0, 0x61, -1}, {0xe0, 0xe1, -1} }, { {0xe0, 0x62, -1}, {0xe0, 0xe2, -1} }, { {0xe0, 0x63, -1}, {0xe0, 0xe3, -1} }, /*e0*/
- { {0xe0, 0x64, -1}, {0xe0, 0xe4, -1} }, { {0xe0, 0x65, -1}, {0xe0, 0xe5, -1} }, { {0xe0, 0x66, -1}, {0xe0, 0xe6, -1} }, { {0xe0, 0x67, -1}, {0xe0, 0xe7, -1} }, /*e4*/
- { {0xe0, 0x68, -1}, {0xe0, 0xe8, -1} }, { {0xe0, 0x69, -1}, {0xe0, 0xe9, -1} }, { {0xe0, 0x6a, -1}, {0xe0, 0xea, -1} }, { {0xe0, 0x6b, -1}, {0xe0, 0xeb, -1} }, /*e8*/
- { {0xe0, 0x6c, -1}, {0xe0, 0xec, -1} }, { {0xe0, 0x6d, -1}, {0xe0, 0xed, -1} }, { {0xe0, 0x6e, -1}, {0xe0, 0xee, -1} }, { {-1}, {-1} }, /*ec*/
- { {0xe0, 0x70, -1}, {0xe0, 0xf0, -1} }, { {0xf1, -1}, {-1} }, { {0xf2, -1}, {-1} }, { {0xe0, 0x73, -1}, {0xe0, 0xf3, -1} }, /*f0*/
- { {0xe0, 0x74, -1}, {0xe0, 0xf4, -1} }, { {0xe0, 0x75, -1}, {0xe0, 0xf5, -1} }, { {-1}, {-1} }, { {0xe0, 0x77, -1}, {0xe0, 0xf7, -1} }, /*f4*/
- { {0xe0, 0x78, -1}, {0xe0, 0xf8, -1} }, { {0xe0, 0x79, -1}, {0xe0, 0xf9, -1} }, { {0xe0, 0x7a, -1}, {0xe0, 0xfa, -1} }, { {0xe0, 0x7b, -1}, {0xe0, 0xfb, -1} }, /*f8*/
- { {0xe0, 0x7c, -1}, {0xe0, 0xfc, -1} }, { {0xe0, 0x7d, -1}, {0xe0, 0xfd, -1} }, { {0xe0, 0x7e, -1}, {0xe0, 0xfe, -1} }, { {0xe1, 0x1d, 0x45, 0xe1, 0x9d, 0xc5, -1}, {-1} }, /*fc*/
- { {-1}, {-1} }, { {0xe0, 0x01, -1}, {0xe0, 0x81, -1} }, { {0xe0, 0x02, -1}, {0xe0, 0x82, -1} }, { {-1}, {-1} }, /*100*/
- { {-1}, {-1} }, { {0xe0, 0x05, -1}, {0xe0, 0x85, -1} }, { {0xe0, 0x06, -1}, {0xe0, 0x86, -1} }, { {0xe0, 0x07, -1}, {0xe0, 0x87, -1} }, /*104*/
- { {0xe0, 0x71, -1}, {0xe0, 0xf1, -1} }, { {0xe0, 0x72, -1}, {0xe0, 0xf2, -1} }, { {0xe0, 0x7f, -1}, {0xe0, 0xff, -1} }, { {0xe0, 0xe1, -1}, {-1} }, /*108*/
- { {0xe0, 0xee, -1}, {-1} }, { {0xe0, 0xf1, -1}, {-1} }, { {0xe0, 0xfe, -1}, {-1} }, { {0xe0, 0xff, -1}, {-1} } /*10c*/
+ { {0x80, 0}, {0} }, { {0x81, 0}, {0} }, { {0x82, 0}, {0} }, { {0xe0, 0x03, 0}, {0xe0, 0x83, 0} }, /*80*/
+ { {0xe0, 0x04, 0}, {0xe0, 0x84, 0} }, { {0x85, 0}, {0} }, { {0x86, 0}, {0} }, { {0x87, 0}, {0} }, /*84*/
+ { {0xe0, 0x08, 0}, {0xe0, 0x88, 0} }, { {0xe0, 0x09, 0}, {0xe0, 0x89, 0} }, { {0xe0, 0x0a, 0}, {0xe0, 0x8a, 0} }, { {0xe0, 0x0b, 0}, {0xe0, 0x8b, 0} }, /*88*/
+ { {0xe0, 0x0c, 0}, {0xe0, 0x8c, 0} }, { {0}, {0} }, { {0xe0, 0x0e, 0}, {0xe0, 0x8e, 0} }, { {0xe0, 0x0f, 0}, {0xe0, 0x8f, 0} }, /*8c*/
+ { {0xe0, 0x10, 0}, {0xe0, 0x90, 0} }, { {0xe0, 0x11, 0}, {0xe0, 0x91, 0} }, { {0xe0, 0x12, 0}, {0xe0, 0x92, 0} }, { {0xe0, 0x13, 0}, {0xe0, 0x93, 0} }, /*90*/
+ { {0xe0, 0x14, 0}, {0xe0, 0x94, 0} }, { {0xe0, 0x15, 0}, {0xe0, 0x95, 0} }, { {0xe0, 0x16, 0}, {0xe0, 0x96, 0} }, { {0xe0, 0x17, 0}, {0xe0, 0x97, 0} }, /*94*/
+ { {0xe0, 0x18, 0}, {0xe0, 0x98, 0} }, { {0xe0, 0x19, 0}, {0xe0, 0x99, 0} }, { {0xe0, 0x1a, 0}, {0xe0, 0x9a, 0} }, { {0xe0, 0x1b, 0}, {0xe0, 0x9b, 0} }, /*98*/
+ { {0xe0, 0x1c, 0}, {0xe0, 0x9c, 0} }, { {0xe0, 0x1d, 0}, {0xe0, 0x9d, 0} }, { {0xe0, 0x1e, 0}, {0xe0, 0x9e, 0} }, { {0xe0, 0x1f, 0}, {0xe0, 0x9f, 0} }, /*9c*/
+ { {0xe0, 0x20, 0}, {0xe0, 0xa0, 0} }, { {0xe0, 0x21, 0}, {0xe0, 0xa1, 0} }, { {0xe0, 0x22, 0}, {0xe0, 0xa2, 0} }, { {0xe0, 0x23, 0}, {0xe0, 0xa3, 0} }, /*a0*/
+ { {0xe0, 0x24, 0}, {0xe0, 0xa4, 0} }, { {0xe0, 0x25, 0}, {0xe0, 0xa5, 0} }, { {0xe0, 0x26, 0}, {0xe0, 0xa6, 0} }, { {0}, {0} }, /*a4*/
+ { {0}, {0} }, { {0}, {0} }, { {0xe0, 0x2a, 0}, {0xe0, 0xaa, 0} }, { {0}, {0} }, /*a8*/
+ { {0xe0, 0x2c, 0}, {0xe0, 0xac, 0} }, { {0xe0, 0x2d, 0}, {0xe0, 0xad, 0} }, { {0xe0, 0x2e, 0}, {0xe0, 0xae, 0} }, { {0xe0, 0x2f, 0}, {0xe0, 0xaf, 0} }, /*ac*/
+ { {0xe0, 0x30, 0}, {0xe0, 0xb0, 0} }, { {0xe0, 0x31, 0}, {0xe0, 0xb1, 0} }, { {0xe0, 0x32, 0}, {0xe0, 0xb2, 0} }, { {0}, {0} }, /*b0*/
+ { {0xe0, 0x34, 0}, {0xe0, 0xb4, 0} }, { {0xe0, 0x35, 0}, {0xe0, 0xb5, 0} }, { {0xe0, 0x36, 0}, {0xe0, 0xb6, 0} }, { {0xe0, 0x37, 0}, {0xe0, 0xb7, 0} }, /*b4*/
+ { {0xe0, 0x38, 0}, {0xe0, 0xb8, 0} }, { {0}, {0} }, { {0xe0, 0x3a, 0}, {0xe0, 0xba, 0} }, { {0xe0, 0x3b, 0}, {0xe0, 0xbb, 0} }, /*b8*/
+ { {0xe0, 0x3c, 0}, {0xe0, 0xbc, 0} }, { {0xe0, 0x3d, 0}, {0xe0, 0xbd, 0} }, { {0xe0, 0x3e, 0}, {0xe0, 0xbe, 0} }, { {0xe0, 0x3f, 0}, {0xe0, 0xbf, 0} }, /*bc*/
+ { {0xe0, 0x40, 0}, {0xe0, 0xc0, 0} }, { {0xe0, 0x41, 0}, {0xe0, 0xc1, 0} }, { {0xe0, 0x42, 0}, {0xe0, 0xc2, 0} }, { {0xe0, 0x43, 0}, {0xe0, 0xc3, 0} }, /*c0*/
+ { {0xe0, 0x44, 0}, {0xe0, 0xc4, 0} }, { {0}, {0} }, { {0xe0, 0x46, 0}, {0xe0, 0xc6, 0} }, { {0xe0, 0x47, 0}, {0xe0, 0xc7, 0} }, /*c4*/
+ { {0xe0, 0x48, 0}, {0xe0, 0xc8, 0} }, { {0xe0, 0x49, 0}, {0xe0, 0xc9, 0} }, { {0}, {0} }, { {0xe0, 0x4b, 0}, {0xe0, 0xcb, 0} }, /*c8*/
+ { {0xe0, 0x4c, 0}, {0xe0, 0xcc, 0} }, { {0xe0, 0x4d, 0}, {0xe0, 0xcd, 0} }, { {0xe0, 0x4e, 0}, {0xe0, 0xce, 0} }, { {0xe0, 0x4f, 0}, {0xe0, 0xcf, 0} }, /*cc*/
+ { {0xe0, 0x50, 0}, {0xe0, 0xd0, 0} }, { {0xe0, 0x51, 0}, {0xe0, 0xd1, 0} }, { {0xe0, 0x52, 0}, {0xe0, 0xd2, 0} }, { {0xe0, 0x53, 0}, {0xe0, 0xd3, 0} }, /*d0*/
+ { {0xd4, 0}, {0} }, { {0xe0, 0x55, 0}, {0xe0, 0xd5, 0} }, { {0}, {0} }, { {0xe0, 0x57, 0}, {0xe0, 0xd7, 0} }, /*d4*/
+ { {0xe0, 0x58, 0}, {0xe0, 0xd8, 0} }, { {0xe0, 0x59, 0}, {0xe0, 0xd9, 0} }, { {0xe0, 0x5a, 0}, {0xe0, 0xaa, 0} }, { {0xe0, 0x5b, 0}, {0xe0, 0xdb, 0} }, /*d8*/
+ { {0xe0, 0x5c, 0}, {0xe0, 0xdc, 0} }, { {0xe0, 0x5d, 0}, {0xe0, 0xdd, 0} }, { {0xe0, 0x5e, 0}, {0xe0, 0xee, 0} }, { {0xe0, 0x5f, 0}, {0xe0, 0xdf, 0} }, /*dc*/
+ { {0}, {0} }, { {0xe0, 0x61, 0}, {0xe0, 0xe1, 0} }, { {0xe0, 0x62, 0}, {0xe0, 0xe2, 0} }, { {0xe0, 0x63, 0}, {0xe0, 0xe3, 0} }, /*e0*/
+ { {0xe0, 0x64, 0}, {0xe0, 0xe4, 0} }, { {0xe0, 0x65, 0}, {0xe0, 0xe5, 0} }, { {0xe0, 0x66, 0}, {0xe0, 0xe6, 0} }, { {0xe0, 0x67, 0}, {0xe0, 0xe7, 0} }, /*e4*/
+ { {0xe0, 0x68, 0}, {0xe0, 0xe8, 0} }, { {0xe0, 0x69, 0}, {0xe0, 0xe9, 0} }, { {0xe0, 0x6a, 0}, {0xe0, 0xea, 0} }, { {0xe0, 0x6b, 0}, {0xe0, 0xeb, 0} }, /*e8*/
+ { {0xe0, 0x6c, 0}, {0xe0, 0xec, 0} }, { {0xe0, 0x6d, 0}, {0xe0, 0xed, 0} }, { {0xe0, 0x6e, 0}, {0xe0, 0xee, 0} }, { {0}, {0} }, /*ec*/
+ { {0xe0, 0x70, 0}, {0xe0, 0xf0, 0} }, { {0xf1, 0}, {0} }, { {0xf2, 0}, {0} }, { {0xe0, 0x73, 0}, {0xe0, 0xf3, 0} }, /*f0*/
+ { {0xe0, 0x74, 0}, {0xe0, 0xf4, 0} }, { {0xe0, 0x75, 0}, {0xe0, 0xf5, 0} }, { {0}, {0} }, { {0xe0, 0x77, 0}, {0xe0, 0xf7, 0} }, /*f4*/
+ { {0xe0, 0x78, 0}, {0xe0, 0xf8, 0} }, { {0xe0, 0x79, 0}, {0xe0, 0xf9, 0} }, { {0xe0, 0x7a, 0}, {0xe0, 0xfa, 0} }, { {0xe0, 0x7b, 0}, {0xe0, 0xfb, 0} }, /*f8*/
+ { {0xe0, 0x7c, 0}, {0xe0, 0xfc, 0} }, { {0xe0, 0x7d, 0}, {0xe0, 0xfd, 0} }, { {0xe0, 0x7e, 0}, {0xe0, 0xfe, 0} }, { {0xe1, 0x1d, 0x45, 0xe1, 0x9d, 0xc5, 0}, {0} }, /*fc*/
+ { {0}, {0} }, { {0xe0, 0x01, 0}, {0xe0, 0x81, 0} }, { {0xe0, 0x02, 0}, {0xe0, 0x82, 0} }, { {0}, {0} }, /*100*/
+ { {0}, {0} }, { {0xe0, 0x05, 0}, {0xe0, 0x85, 0} }, { {0xe0, 0x06, 0}, {0xe0, 0x86, 0} }, { {0xe0, 0x07, 0}, {0xe0, 0x87, 0} }, /*104*/
+ { {0xe0, 0x71, 0}, {0xe0, 0xf1, 0} }, { {0xe0, 0x72, 0}, {0xe0, 0xf2, 0} }, { {0xe0, 0x7f, 0}, {0xe0, 0xff, 0} }, { {0xe0, 0xe1, 0}, {0} }, /*108*/
+ { {0xe0, 0xee, 0}, {0} }, { {0xe0, 0xf1, 0}, {0} }, { {0xe0, 0xfe, 0}, {0} }, { {0xe0, 0xff, 0}, {0} } /*10c*/
+};
+
+/*272 = 256 + 16 fake interim scancodes for disambiguation purposes.*/
+static scancode scancode_set2[272] =
+{
+ { {0}, {0} }, { {0x76, 0}, {0xf0, 0x76, 0} }, { {0x16, 0}, {0xf0, 0x16, 0} }, { {0x1e, 0}, {0xf0, 0x1e, 0} },
+ { {0x26, 0}, {0xf0, 0x26, 0} }, { {0x25, 0}, {0xf0, 0x25, 0} }, { {0x2e, 0}, {0xf0, 0x2e, 0} }, { {0x36, 0}, {0xf0, 0x36, 0} },
+ { {0x3d, 0}, {0xf0, 0x3d, 0} }, { {0x3e, 0}, {0xf0, 0x3e, 0} }, { {0x46, 0}, {0xf0, 0x46, 0} }, { {0x45, 0}, {0xf0, 0x45, 0} },
+ { {0x4e, 0}, {0xf0, 0x4e, 0} }, { {0x55, 0}, {0xf0, 0x55, 0} }, { {0x66, 0}, {0xf0, 0x66, 0} }, { {0x0d, 0}, {0xf0, 0x0d, 0} },
+ { {0x15, 0}, {0xf0, 0x15, 0} }, { {0x1d, 0}, {0xf0, 0x1d, 0} }, { {0x24, 0}, {0xf0, 0x24, 0} }, { {0x2d, 0}, {0xf0, 0x2d, 0} },
+ { {0x2c, 0}, {0xf0, 0x2c, 0} }, { {0x35, 0}, {0xf0, 0x35, 0} }, { {0x3c, 0}, {0xf0, 0x3c, 0} }, { {0x43, 0}, {0xf0, 0x43, 0} },
+ { {0x44, 0}, {0xf0, 0x44, 0} }, { {0x4d, 0}, {0xf0, 0x4d, 0} }, { {0x54, 0}, {0xf0, 0x54, 0} }, { {0x5b, 0}, {0xf0, 0x5b, 0} },
+ { {0x5a, 0}, {0xf0, 0x5a, 0} }, { {0x14, 0}, {0xf0, 0x14, 0} }, { {0x1c, 0}, {0xf0, 0x1c, 0} }, { {0x1b, 0}, {0xf0, 0x1b, 0} },
+ { {0x23, 0}, {0xf0, 0x23, 0} }, { {0x2b, 0}, {0xf0, 0x2b, 0} }, { {0x34, 0}, {0xf0, 0x34, 0} }, { {0x33, 0}, {0xf0, 0x33, 0} },
+ { {0x3b, 0}, {0xf0, 0x3b, 0} }, { {0x42, 0}, {0xf0, 0x42, 0} }, { {0x4b, 0}, {0xf0, 0x4b, 0} }, { {0x4c, 0}, {0xf0, 0x4c, 0} },
+ { {0x52, 0}, {0xf0, 0x52, 0} }, { {0x0e, 0}, {0xf0, 0x0e, 0} }, { {0x12, 0}, {0xf0, 0x12, 0} }, { {0x5d, 0}, {0xf0, 0x5d, 0} },
+ { {0x1a, 0}, {0xf0, 0x1a, 0} }, { {0x22, 0}, {0xf0, 0x22, 0} }, { {0x21, 0}, {0xf0, 0x21, 0} }, { {0x2a, 0}, {0xf0, 0x2a, 0} },
+ { {0x32, 0}, {0xf0, 0x32, 0} }, { {0x31, 0}, {0xf0, 0x31, 0} }, { {0x3a, 0}, {0xf0, 0x3a, 0} }, { {0x41, 0}, {0xf0, 0x41, 0} },
+ { {0x49, 0}, {0xf0, 0x49, 0} }, { {0x4a, 0}, {0xf0, 0x4a, 0} }, { {0x59, 0}, {0xf0, 0x59, 0} }, { {0x7c, 0}, {0xf0, 0x7c, 0} },
+ { {0x11, 0}, {0xf0, 0x11, 0} }, { {0x29, 0}, {0xf0, 0x29, 0} }, { {0x58, 0}, {0xf0, 0x58, 0} }, { {0x05, 0}, {0xf0, 0x05, 0} },
+ { {0x06, 0}, {0xf0, 0x06, 0} }, { {0x04, 0}, {0xf0, 0x04, 0} }, { {0x0c, 0}, {0xf0, 0x0c, 0} }, { {0x03, 0}, {0xf0, 0x03, 0} },
+ { {0x0b, 0}, {0xf0, 0x0b, 0} }, { {0x83, 0}, {0xf0, 0x83, 0} }, { {0x0a, 0}, {0xf0, 0x0a, 0} }, { {0x01, 0}, {0xf0, 0x01, 0} },
+ { {0x09, 0}, {0xf0, 0x09, 0} }, { {0x77, 0}, {0xf0, 0x77, 0} }, { {0x7e, 0}, {0xf0, 0x7e, 0} }, { {0x6c, 0}, {0xf0, 0x6c, 0} },
+ { {0x75, 0}, {0xf0, 0x75, 0} }, { {0x7d, 0}, {0xf0, 0x7d, 0} }, { {0x7b, 0}, {0xf0, 0x7b, 0} }, { {0x6b, 0}, {0xf0, 0x6b, 0} },
+ { {0x73, 0}, {0xf0, 0x73, 0} }, { {0x74, 0}, {0xf0, 0x74, 0} }, { {0x79, 0}, {0xf0, 0x79, 0} }, { {0x69, 0}, {0xf0, 0x69, 0} },
+ { {0x72, 0}, {0xf0, 0x72, 0} }, { {0x7a, 0}, {0xf0, 0x7a, 0} }, { {0x70, 0}, {0xf0, 0x70, 0} }, { {0x71, 0}, {0xf0, 0x71, 0} },
+ { {0x84, 0}, {0xf0, 0x84, 0} }, { {0, 0}, {0, 0} }, { {0x61, 0}, {0xf0, 0x61, 0} }, { {0x78, 0}, {0xf0, 0x78, 0} },
+ { {0x07, 0}, {0xf0, 0x07, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0xe0, 0x5a, 0}, {0xe0, 0xf0, 0x5a, 0} }, { {0xe0, 0x14, 0}, {0xe0, 0xf0, 0x14, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0xe0, 0x4a, 0}, {0xe0, 0xf0, 0x4a, 0} }, { {0, 0}, {0, 0} }, { {0xe0, 0x7c, 0}, {0xe0, 0xf0, 0x7c, 0} },
+ { {0xe0, 0x11, 0}, {0xe0, 0xf0, 0x11, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0xe0, 0x6c, 0}, {0xe0, 0xf0, 0x6c, 0} },
+ { {0xe0, 0x75, 0}, {0xe0, 0xf0, 0x75, 0} }, { {0xe0, 0x7d, 0}, {0xe0, 0xf0, 0x7d, 0} }, { {0, 0}, {0, 0} }, { {0xe0, 0x6b, 0}, {0xe0, 0xf0, 0x6b, 0} },
+ { {0, 0}, {0, 0} }, { {0xe0, 0x74, 0}, {0xe0, 0xf0, 0x74, 0} }, { {0, 0}, {0, 0} }, { {0xe0, 0x69, 0}, {0xe0, 0xf0, 0x69, 0} },
+ { {0xe0, 0x72, 0}, {0xe0, 0xf0, 0x72, 0} }, { {0xe0, 0x7a, 0}, {0xe0, 0xf0, 0x7a, 0} }, { {0xe0, 0x70, 0}, {0xe0, 0xf0, 0x70, 0} }, { {0xe0, 0x71, 0}, {0xe0, 0xf0, 0x71, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0xe0, 0x1f, 0}, {0xe0, 0xf0, 0x1f, 0} },
+ { {0xe0, 0x27, 0}, {0xe0, 0xf0, 0x27, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+
+ { {0}, {0} }, { {0xe0, 0x01, 0}, {0xe0, 0xf0, 0x01, 0} }, { {0xe0, 0x02, 0}, {0xe0, 0xf0, 0x02, 0} }, { {0}, {0} }, /*100*/
+ { {0}, {0} }, { {0xe0, 0x05, 0}, {0xe0, 0xf0, 0x15, 0} }, { {0xe0, 0x06, 0}, {0xe0, 0xf0, 0x06, 0} }, { {0xe0, 0x07, 0}, {0xe0, 0xf0, 0x07, 0} }, /*104*/
+ { {0xe0, 0x71, 0}, {0xe0, 0xf0, 0x71, 0} }, { {0xe0, 0x72, 0}, {0xe0, 0xf0, 0x72, 0} }, { {0xe0, 0x7f, 0}, {0xe0, 0xf0, 0x7f, 0} }, { {0xe0, 0xe1, 0}, {0} }, /*108*/
+ { {0xe0, 0xee, 0}, {0} }, { {0xe0, 0xf1, 0}, {0} }, { {0xe0, 0xfe, 0}, {0} }, { {0xe0, 0xff, 0}, {0} } /*10c*/
+};
+
+/*272 = 256 + 16 fake interim scancodes for disambiguation purposes.*/
+static scancode scancode_set3[272] =
+{
+ { {0}, {0} }, { {0x76, 0}, {0xf0, 0x76, 0} }, { {0x16, 0}, {0xf0, 0x16, 0} }, { {0x1e, 0}, {0xf0, 0x1e, 0} },
+ { {0x26, 0}, {0xf0, 0x26, 0} }, { {0x25, 0}, {0xf0, 0x25, 0} }, { {0x2e, 0}, {0xf0, 0x2e, 0} }, { {0x36, 0}, {0xf0, 0x36, 0} },
+ { {0x3d, 0}, {0xf0, 0x3d, 0} }, { {0x3e, 0}, {0xf0, 0x3e, 0} }, { {0x46, 0}, {0xf0, 0x46, 0} }, { {0x45, 0}, {0xf0, 0x45, 0} },
+ { {0x4e, 0}, {0xf0, 0x4e, 0} }, { {0x55, 0}, {0xf0, 0x55, 0} }, { {0x66, 0}, {0xf0, 0x66, 0} }, { {0x0d, 0}, {0xf0, 0x0d, 0} },
+ { {0x15, 0}, {0xf0, 0x15, 0} }, { {0x1d, 0}, {0xf0, 0x1d, 0} }, { {0x24, 0}, {0xf0, 0x24, 0} }, { {0x2d, 0}, {0xf0, 0x2d, 0} },
+ { {0x2c, 0}, {0xf0, 0x2c, 0} }, { {0x35, 0}, {0xf0, 0x35, 0} }, { {0x3c, 0}, {0xf0, 0x3c, 0} }, { {0x43, 0}, {0xf0, 0x43, 0} },
+ { {0x44, 0}, {0xf0, 0x44, 0} }, { {0x4d, 0}, {0xf0, 0x4d, 0} }, { {0x54, 0}, {0xf0, 0x54, 0} }, { {0x5b, 0}, {0xf0, 0x5b, 0} },
+ { {0x5a, 0}, {0xf0, 0x5a, 0} }, { {0x19, 0}, {0xf0, 0x19, 0} }, { {0x1c, 0}, {0xf0, 0x1c, 0} }, { {0x1b, 0}, {0xf0, 0x1b, 0} },
+ { {0x23, 0}, {0xf0, 0x23, 0} }, { {0x2b, 0}, {0xf0, 0x2b, 0} }, { {0x34, 0}, {0xf0, 0x34, 0} }, { {0x33, 0}, {0xf0, 0x33, 0} },
+ { {0x3b, 0}, {0xf0, 0x3b, 0} }, { {0x42, 0}, {0xf0, 0x42, 0} }, { {0x4b, 0}, {0xf0, 0x4b, 0} }, { {0x4c, 0}, {0xf0, 0x4c, 0} },
+ { {0x52, 0}, {0xf0, 0x52, 0} }, { {0x0e, 0}, {0xf0, 0x0e, 0} }, { {0x12, 0}, {0xf0, 0x12, 0} }, { {0x5c, 0}, {0xf0, 0x5c, 0} },
+ { {0x1a, 0}, {0xf0, 0x1a, 0} }, { {0x22, 0}, {0xf0, 0x22, 0} }, { {0x21, 0}, {0xf0, 0x21, 0} }, { {0x2a, 0}, {0xf0, 0x2a, 0} },
+ { {0x32, 0}, {0xf0, 0x32, 0} }, { {0x31, 0}, {0xf0, 0x31, 0} }, { {0x3a, 0}, {0xf0, 0x3a, 0} }, { {0x41, 0}, {0xf0, 0x41, 0} },
+ { {0x49, 0}, {0xf0, 0x49, 0} }, { {0x4a, 0}, {0xf0, 0x4a, 0} }, { {0x59, 0}, {0xf0, 0x59, 0} }, { {0x7c, 0}, {0xf0, 0x7c, 0} },
+ { {0x11, 0}, {0xf0, 0x11, 0} }, { {0x29, 0}, {0xf0, 0x29, 0} }, { {0x14, 0}, {0xf0, 0x14, 0} }, { {0x05, 0}, {0xf0, 0x05, 0} },
+ { {0x06, 0}, {0xf0, 0x06, 0} }, { {0x04, 0}, {0xf0, 0x04, 0} }, { {0x0c, 0}, {0xf0, 0x0c, 0} }, { {0x03, 0}, {0xf0, 0x03, 0} },
+ { {0x0b, 0}, {0xf0, 0x0b, 0} }, { {0x83, 0}, {0xf0, 0x83, 0} }, { {0x0a, 0}, {0xf0, 0x0a, 0} }, { {0x01, 0}, {0xf0, 0x01, 0} },
+ { {0x09, 0}, {0xf0, 0x09, 0} }, { {0x77, 0}, {0xf0, 0x77, 0} }, { {0x7e, 0}, {0xf0, 0x7e, 0} }, { {0x6c, 0}, {0xf0, 0x6c, 0} },
+ { {0x75, 0}, {0xf0, 0x75, 0} }, { {0x7d, 0}, {0xf0, 0x7d, 0} }, { {0x7b, 0}, {0xf0, 0x7b, 0} }, { {0x6b, 0}, {0xf0, 0x6b, 0} },
+ { {0x73, 0}, {0xf0, 0x73, 0} }, { {0x74, 0}, {0xf0, 0x74, 0} }, { {0x79, 0}, {0xf0, 0x79, 0} }, { {0x69, 0}, {0xf0, 0x69, 0} },
+ { {0x72, 0}, {0xf0, 0x72, 0} }, { {0x7a, 0}, {0xf0, 0x7a, 0} }, { {0x70, 0}, {0xf0, 0x70, 0} }, { {0x71, 0}, {0xf0, 0x71, 0} },
+ { {0x84, 0}, {0xf0, 0x84, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0x78, 0}, {0xf0, 0x78, 0} },
+ { {0x07, 0}, {0xf0, 0x07, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0x79, 0}, {0xf0, 0x79, 0} }, { {0x58, 0}, {0xf0, 0x58, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0x77, 0}, {0xf0, 0x77, 0} }, { {0, 0}, {0, 0} }, { {0x57, 0}, {0xf0, 0x57, 0} },
+ { {0x39, 0}, {0xf0, 0x39, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0x6e, 0}, {0xf0, 0x6e, 0} },
+ { {0x63, 0}, {0xf0, 0x63, 0} }, { {0x6f, 0}, {0xf0, 0x6f, 0} }, { {0, 0}, {0, 0} }, { {0x61, 0}, {0xf0, 0x61, 0} },
+ { {0, 0}, {0, 0} }, { {0x6a, 0}, {0xf0, 0x6a, 0} }, { {0, 0}, {0, 0} }, { {0x65, 0}, {0xf0, 0x65, 0} },
+ { {0x60, 0}, {0xf0, 0x60, 0} }, { {0x6d, 0}, {0xf0, 0x6d, 0} }, { {0x67, 0}, {0xf0, 0x67, 0} }, { {0x64, 0}, {0xf0, 0x64, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0x8b, 0}, {0xf0, 0x8b, 0} },
+ { {0x8c, 0}, {0xf0, 0x8c, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
};
/*XT keyboard has no escape scancodes, and no scancodes beyond 53*/
static scancode scancode_xt[272] =
{
- { {-1}, {-1} }, { {0x01, -1}, {0x81, -1} }, { {0x02, -1}, {0x82, -1} }, { {0x03, -1}, {0x83, -1} },
- { {0x04, -1}, {0x84, -1} }, { {0x05, -1}, {0x85, -1} }, { {0x06, -1}, {0x86, -1} }, { {0x07, -1}, {0x87, -1} },
- { {0x08, -1}, {0x88, -1} }, { {0x09, -1}, {0x89, -1} }, { {0x0a, -1}, {0x8a, -1} }, { {0x0b, -1}, {0x8b, -1} },
- { {0x0c, -1}, {0x8c, -1} }, { {0x0d, -1}, {0x8d, -1} }, { {0x0e, -1}, {0x8e, -1} }, { {0x0f, -1}, {0x8f, -1} },
- { {0x10, -1}, {0x90, -1} }, { {0x11, -1}, {0x91, -1} }, { {0x12, -1}, {0x92, -1} }, { {0x13, -1}, {0x93, -1} },
- { {0x14, -1}, {0x94, -1} }, { {0x15, -1}, {0x95, -1} }, { {0x16, -1}, {0x96, -1} }, { {0x17, -1}, {0x97, -1} },
- { {0x18, -1}, {0x98, -1} }, { {0x19, -1}, {0x99, -1} }, { {0x1a, -1}, {0x9a, -1} }, { {0x1b, -1}, {0x9b, -1} },
- { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, { {0x1e, -1}, {0x9e, -1} }, { {0x1f, -1}, {0x9f, -1} },
- { {0x20, -1}, {0xa0, -1} }, { {0x21, -1}, {0xa1, -1} }, { {0x22, -1}, {0xa2, -1} }, { {0x23, -1}, {0xa3, -1} },
- { {0x24, -1}, {0xa4, -1} }, { {0x25, -1}, {0xa5, -1} }, { {0x26, -1}, {0xa6, -1} }, { {0x27, -1}, {0xa7, -1} },
- { {0x28, -1}, {0xa8, -1} }, { {0x29, -1}, {0xa9, -1} }, { {0x2a, -1}, {0xaa, -1} }, { {0x2b, -1}, {0xab, -1} },
- { {0x2c, -1}, {0xac, -1} }, { {0x2d, -1}, {0xad, -1} }, { {0x2e, -1}, {0xae, -1} }, { {0x2f, -1}, {0xaf, -1} },
- { {0x30, -1}, {0xb0, -1} }, { {0x31, -1}, {0xb1, -1} }, { {0x32, -1}, {0xb2, -1} }, { {0x33, -1}, {0xb3, -1} },
- { {0x34, -1}, {0xb4, -1} }, { {0x35, -1}, {0xb5, -1} }, { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} },
- { {0x38, -1}, {0xb8, -1} }, { {0x39, -1}, {0xb9, -1} }, { {0x3a, -1}, {0xba, -1} }, { {0x3b, -1}, {0xbb, -1} },
- { {0x3c, -1}, {0xbc, -1} }, { {0x3d, -1}, {0xbd, -1} }, { {0x3e, -1}, {0xbe, -1} }, { {0x3f, -1}, {0xbf, -1} },
- { {0x40, -1}, {0xc0, -1} }, { {0x41, -1}, {0xc1, -1} }, { {0x42, -1}, {0xc2, -1} }, { {0x43, -1}, {0xc3, -1} },
- { {0x44, -1}, {0xc4, -1} }, { {0x45, -1}, {0xc5, -1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} },
- { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, { {0x4a, -1}, {0xca, -1} }, { {0x4b, -1}, {0xcb, -1} },
- { {0x4c, -1}, {0xcc, -1} }, { {0x4d, -1}, {0xcd, -1} }, { {0x4e, -1}, {0xce, -1} }, { {0x4f, -1}, {0xcf, -1} },
- { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x53, -1}, {0xd3, -1} },
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*54*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*58*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*5c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*60*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*64*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*68*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*6c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*70*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*74*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*78*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*7c*/
+ { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} },
+ { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, { {0x06, 0}, {0x86, 0} }, { {0x07, 0}, {0x87, 0} },
+ { {0x08, 0}, {0x88, 0} }, { {0x09, 0}, {0x89, 0} }, { {0x0a, 0}, {0x8a, 0} }, { {0x0b, 0}, {0x8b, 0} },
+ { {0x0c, 0}, {0x8c, 0} }, { {0x0d, 0}, {0x8d, 0} }, { {0x0e, 0}, {0x8e, 0} }, { {0x0f, 0}, {0x8f, 0} },
+ { {0x10, 0}, {0x90, 0} }, { {0x11, 0}, {0x91, 0} }, { {0x12, 0}, {0x92, 0} }, { {0x13, 0}, {0x93, 0} },
+ { {0x14, 0}, {0x94, 0} }, { {0x15, 0}, {0x95, 0} }, { {0x16, 0}, {0x96, 0} }, { {0x17, 0}, {0x97, 0} },
+ { {0x18, 0}, {0x98, 0} }, { {0x19, 0}, {0x99, 0} }, { {0x1a, 0}, {0x9a, 0} }, { {0x1b, 0}, {0x9b, 0} },
+ { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, { {0x1e, 0}, {0x9e, 0} }, { {0x1f, 0}, {0x9f, 0} },
+ { {0x20, 0}, {0xa0, 0} }, { {0x21, 0}, {0xa1, 0} }, { {0x22, 0}, {0xa2, 0} }, { {0x23, 0}, {0xa3, 0} },
+ { {0x24, 0}, {0xa4, 0} }, { {0x25, 0}, {0xa5, 0} }, { {0x26, 0}, {0xa6, 0} }, { {0x27, 0}, {0xa7, 0} },
+ { {0x28, 0}, {0xa8, 0} }, { {0x29, 0}, {0xa9, 0} }, { {0x2a, 0}, {0xaa, 0} }, { {0x2b, 0}, {0xab, 0} },
+ { {0x2c, 0}, {0xac, 0} }, { {0x2d, 0}, {0xad, 0} }, { {0x2e, 0}, {0xae, 0} }, { {0x2f, 0}, {0xaf, 0} },
+ { {0x30, 0}, {0xb0, 0} }, { {0x31, 0}, {0xb1, 0} }, { {0x32, 0}, {0xb2, 0} }, { {0x33, 0}, {0xb3, 0} },
+ { {0x34, 0}, {0xb4, 0} }, { {0x35, 0}, {0xb5, 0} }, { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} },
+ { {0x38, 0}, {0xb8, 0} }, { {0x39, 0}, {0xb9, 0} }, { {0x3a, 0}, {0xba, 0} }, { {0x3b, 0}, {0xbb, 0} },
+ { {0x3c, 0}, {0xbc, 0} }, { {0x3d, 0}, {0xbd, 0} }, { {0x3e, 0}, {0xbe, 0} }, { {0x3f, 0}, {0xbf, 0} },
+ { {0x40, 0}, {0xc0, 0} }, { {0x41, 0}, {0xc1, 0} }, { {0x42, 0}, {0xc2, 0} }, { {0x43, 0}, {0xc3, 0} },
+ { {0x44, 0}, {0xc4, 0} }, { {0x45, 0}, {0xc5, 0} }, { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} },
+ { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, { {0x4a, 0}, {0xca, 0} }, { {0x4b, 0}, {0xcb, 0} },
+ { {0x4c, 0}, {0xcc, 0} }, { {0x4d, 0}, {0xcd, 0} }, { {0x4e, 0}, {0xce, 0} }, { {0x4f, 0}, {0xcf, 0} },
+ { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} },
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*54*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*58*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*5c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*60*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*64*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*68*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*6c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*70*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*74*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*78*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*7c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*80*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*84*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*88*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*8c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*90*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*94*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*98*/
- { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*9c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*a0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*a4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {0x2a, -1}, {0xaa, -1} }, { {-1}, {-1} }, /*a8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*ac*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*b0*/
- { {-1}, {-1} }, { {0x35, -1}, {0xb5, -1} }, { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} }, /*b4*/
- { {0x38, -1}, {0xb8, -1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*b8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*bc*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*c0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} }, /*c4*/
- { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, { {-1}, {-1} }, { {0x4b, -1}, {0xcb, -1} }, /*c8*/
- { {-1}, {-1} }, { {0x4d, -1}, {0xcd, -1} }, { {-1}, {-1} }, { {0x4f, -1}, {0xcf, -1} }, /*cc*/
- { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x53, -1}, {0xd3, -1} }, /*d0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*d4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*d8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*dc*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*ec*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*fc*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*100*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*104*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*108*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*10c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*80*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*84*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*88*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*8c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*90*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*94*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*98*/
+ { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, { {0}, {0} }, { {0}, {0} }, /*9c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*a0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*a4*/
+ { {0}, {0} }, { {0}, {0} }, { {0x2a, 0}, {0xaa, 0} }, { {0}, {0} }, /*a8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*ac*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*b0*/
+ { {0}, {0} }, { {0x35, 0}, {0xb5, 0} }, { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} }, /*b4*/
+ { {0x38, 0}, {0xb8, 0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*b8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*bc*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*c0*/
+ { {0}, {0} }, { {0}, {0} }, { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, /*c4*/
+ { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, { {0}, {0} }, { {0x4b, 0}, {0xcb, 0} }, /*c8*/
+ { {0}, {0} }, { {0x4d, 0}, {0xcd, 0} }, { {0}, {0} }, { {0x4f, 0}, {0xcf, 0} }, /*cc*/
+ { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, /*d0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*d4*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*d8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*dc*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*e0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*e4*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*e8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*ec*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*f0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*f4*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*f8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*fc*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*100*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*104*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*108*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*10c*/
};
/*Tandy keyboard has slightly different scancodes to XT*/
static scancode scancode_tandy[272] =
{
- { {-1}, {-1} }, { {0x01, -1}, {0x81, -1} }, { {0x02, -1}, {0x82, -1} }, { {0x03, -1}, {0x83, -1} },
- { {0x04, -1}, {0x84, -1} }, { {0x05, -1}, {0x85, -1} }, { {0x06, -1}, {0x86, -1} }, { {0x07, -1}, {0x87, -1} },
- { {0x08, -1}, {0x88, -1} }, { {0x09, -1}, {0x89, -1} }, { {0x0a, -1}, {0x8a, -1} }, { {0x0b, -1}, {0x8b, -1} },
- { {0x0c, -1}, {0x8c, -1} }, { {0x0d, -1}, {0x8d, -1} }, { {0x0e, -1}, {0x8e, -1} }, { {0x0f, -1}, {0x8f, -1} },
- { {0x10, -1}, {0x90, -1} }, { {0x11, -1}, {0x91, -1} }, { {0x12, -1}, {0x92, -1} }, { {0x13, -1}, {0x93, -1} },
- { {0x14, -1}, {0x94, -1} }, { {0x15, -1}, {0x95, -1} }, { {0x16, -1}, {0x96, -1} }, { {0x17, -1}, {0x97, -1} },
- { {0x18, -1}, {0x98, -1} }, { {0x19, -1}, {0x99, -1} }, { {0x1a, -1}, {0x9a, -1} }, { {0x1b, -1}, {0x9b, -1} },
- { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, { {0x1e, -1}, {0x9e, -1} }, { {0x1f, -1}, {0x9f, -1} },
- { {0x20, -1}, {0xa0, -1} }, { {0x21, -1}, {0xa1, -1} }, { {0x22, -1}, {0xa2, -1} }, { {0x23, -1}, {0xa3, -1} },
- { {0x24, -1}, {0xa4, -1} }, { {0x25, -1}, {0xa5, -1} }, { {0x26, -1}, {0xa6, -1} }, { {0x27, -1}, {0xa7, -1} },
- { {0x28, -1}, {0xa8, -1} }, { {0x29, -1}, {0xa9, -1} }, { {0x2a, -1}, {0xaa, -1} }, { {0x47, -1}, {0xc7, -1} },
- { {0x2c, -1}, {0xac, -1} }, { {0x2d, -1}, {0xad, -1} }, { {0x2e, -1}, {0xae, -1} }, { {0x2f, -1}, {0xaf, -1} },
- { {0x30, -1}, {0xb0, -1} }, { {0x31, -1}, {0xb1, -1} }, { {0x32, -1}, {0xb2, -1} }, { {0x33, -1}, {0xb3, -1} },
- { {0x34, -1}, {0xb4, -1} }, { {0x35, -1}, {0xb5, -1} }, { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} },
- { {0x38, -1}, {0xb8, -1} }, { {0x39, -1}, {0xb9, -1} }, { {0x3a, -1}, {0xba, -1} }, { {0x3b, -1}, {0xbb, -1} },
- { {0x3c, -1}, {0xbc, -1} }, { {0x3d, -1}, {0xbd, -1} }, { {0x3e, -1}, {0xbe, -1} }, { {0x3f, -1}, {0xbf, -1} },
- { {0x40, -1}, {0xc0, -1} }, { {0x41, -1}, {0xc1, -1} }, { {0x42, -1}, {0xc2, -1} }, { {0x43, -1}, {0xc3, -1} },
- { {0x44, -1}, {0xc4, -1} }, { {0x45, -1}, {0xc5, -1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} },
- { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, { {0x4a, -1}, {0xca, -1} }, { {0x4b, -1}, {0xcb, -1} },
- { {0x4c, -1}, {0xcc, -1} }, { {0x4d, -1}, {0xcd, -1} }, { {0x4e, -1}, {0xce, -1} }, { {0x4f, -1}, {0xcf, -1} },
- { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x56, -1}, {0xd6, -1} },
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*54*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*58*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*5c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*60*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*64*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*68*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*6c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*70*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*74*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*78*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*7c*/
+ { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} },
+ { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, { {0x06, 0}, {0x86, 0} }, { {0x07, 0}, {0x87, 0} },
+ { {0x08, 0}, {0x88, 0} }, { {0x09, 0}, {0x89, 0} }, { {0x0a, 0}, {0x8a, 0} }, { {0x0b, 0}, {0x8b, 0} },
+ { {0x0c, 0}, {0x8c, 0} }, { {0x0d, 0}, {0x8d, 0} }, { {0x0e, 0}, {0x8e, 0} }, { {0x0f, 0}, {0x8f, 0} },
+ { {0x10, 0}, {0x90, 0} }, { {0x11, 0}, {0x91, 0} }, { {0x12, 0}, {0x92, 0} }, { {0x13, 0}, {0x93, 0} },
+ { {0x14, 0}, {0x94, 0} }, { {0x15, 0}, {0x95, 0} }, { {0x16, 0}, {0x96, 0} }, { {0x17, 0}, {0x97, 0} },
+ { {0x18, 0}, {0x98, 0} }, { {0x19, 0}, {0x99, 0} }, { {0x1a, 0}, {0x9a, 0} }, { {0x1b, 0}, {0x9b, 0} },
+ { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, { {0x1e, 0}, {0x9e, 0} }, { {0x1f, 0}, {0x9f, 0} },
+ { {0x20, 0}, {0xa0, 0} }, { {0x21, 0}, {0xa1, 0} }, { {0x22, 0}, {0xa2, 0} }, { {0x23, 0}, {0xa3, 0} },
+ { {0x24, 0}, {0xa4, 0} }, { {0x25, 0}, {0xa5, 0} }, { {0x26, 0}, {0xa6, 0} }, { {0x27, 0}, {0xa7, 0} },
+ { {0x28, 0}, {0xa8, 0} }, { {0x29, 0}, {0xa9, 0} }, { {0x2a, 0}, {0xaa, 0} }, { {0x47, 0}, {0xc7, 0} },
+ { {0x2c, 0}, {0xac, 0} }, { {0x2d, 0}, {0xad, 0} }, { {0x2e, 0}, {0xae, 0} }, { {0x2f, 0}, {0xaf, 0} },
+ { {0x30, 0}, {0xb0, 0} }, { {0x31, 0}, {0xb1, 0} }, { {0x32, 0}, {0xb2, 0} }, { {0x33, 0}, {0xb3, 0} },
+ { {0x34, 0}, {0xb4, 0} }, { {0x35, 0}, {0xb5, 0} }, { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} },
+ { {0x38, 0}, {0xb8, 0} }, { {0x39, 0}, {0xb9, 0} }, { {0x3a, 0}, {0xba, 0} }, { {0x3b, 0}, {0xbb, 0} },
+ { {0x3c, 0}, {0xbc, 0} }, { {0x3d, 0}, {0xbd, 0} }, { {0x3e, 0}, {0xbe, 0} }, { {0x3f, 0}, {0xbf, 0} },
+ { {0x40, 0}, {0xc0, 0} }, { {0x41, 0}, {0xc1, 0} }, { {0x42, 0}, {0xc2, 0} }, { {0x43, 0}, {0xc3, 0} },
+ { {0x44, 0}, {0xc4, 0} }, { {0x45, 0}, {0xc5, 0} }, { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} },
+ { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, { {0x4a, 0}, {0xca, 0} }, { {0x4b, 0}, {0xcb, 0} },
+ { {0x4c, 0}, {0xcc, 0} }, { {0x4d, 0}, {0xcd, 0} }, { {0x4e, 0}, {0xce, 0} }, { {0x4f, 0}, {0xcf, 0} },
+ { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, { {0x52, 0}, {0xd2, 0} }, { {0x56, 0}, {0xd6, 0} },
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*54*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*58*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*5c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*60*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*64*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*68*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*6c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*70*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*74*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*78*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*7c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*80*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*84*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*88*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*8c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*90*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*94*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*98*/
- { {0x57, -1}, {0xd7, -1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*9c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*a0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*a4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {0x2a, -1}, {0xaa, -1} }, { {-1}, {-1} }, /*a8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*ac*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*b0*/
- { {-1}, {-1} }, { {0x35, -1}, {0xb5, -1} }, { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} }, /*b4*/
- { {0x38, -1}, {0xb8, -1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*b8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*bc*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*c0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} }, /*c4*/
- { {0x29, -1}, {0xa9, -1} }, { {0x49, -1}, {0xc9, -1} }, { {-1}, {-1} }, { {0x2b, -1}, {0xab, -1} }, /*c8*/
- { {-1}, {-1} }, { {0x4e, -1}, {0xce, -1} }, { {-1}, {-1} }, { {0x4f, -1}, {0xcf, -1} }, /*cc*/
- { {0x4a, -1}, {0xca, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x53, -1}, {0xd3, -1} }, /*d0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*d4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*d8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*dc*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*ec*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*fc*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*100*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*104*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*108*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*10c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*80*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*84*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*88*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*8c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*90*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*94*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*98*/
+ { {0x57, 0}, {0xd7, 0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*9c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*a0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*a4*/
+ { {0}, {0} }, { {0}, {0} }, { {0x2a, 0}, {0xaa, 0} }, { {0}, {0} }, /*a8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*ac*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*b0*/
+ { {0}, {0} }, { {0x35, 0}, {0xb5, 0} }, { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} }, /*b4*/
+ { {0x38, 0}, {0xb8, 0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*b8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*bc*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*c0*/
+ { {0}, {0} }, { {0}, {0} }, { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, /*c4*/
+ { {0x29, 0}, {0xa9, 0} }, { {0x49, 0}, {0xc9, 0} }, { {0}, {0} }, { {0x2b, 0}, {0xab, 0} }, /*c8*/
+ { {0}, {0} }, { {0x4e, 0}, {0xce, 0} }, { {0}, {0} }, { {0x4f, 0}, {0xcf, 0} }, /*cc*/
+ { {0x4a, 0}, {0xca, 0} }, { {0x51, 0}, {0xd1, 0} }, { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, /*d0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*d4*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*d8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*dc*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*e0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*e4*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*e8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*ec*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*f0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*f4*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*f8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*fc*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*100*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*104*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*108*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*10c*/
};
-static int oldkey[272];
-static int keydelay[272];
+static uint8_t oldkey[272];
+static uint8_t keydelay[272];
void (*keyboard_send)(uint8_t val);
void (*keyboard_poll)();
int keyboard_scan = 1;
+static scancode *at_scancodes;
+
+void keyboard_set_scancode_set(int set)
+{
+ switch (set)
+ {
+ case SCANCODE_SET_1:
+ at_scancodes = scancode_set1;
+ break;
+ case SCANCODE_SET_2:
+ at_scancodes = scancode_set2;
+ break;
+ case SCANCODE_SET_3:
+ at_scancodes = scancode_set3;
+ break;
+ default:
+ pclog("Invalid scancode set: %i\n", set);
+ }
+}
+
void keyboard_process()
{
int c;
int d;
- scancode *scancodes = (AT) ? scancode_set1 : scancode_xt;
+ scancode *scancodes = (AT || romset == ROM_XI8088) ? at_scancodes : scancode_xt;
if (!keyboard_scan) return;
if (TANDY) scancodes = scancode_tandy;
@@ -259,20 +429,20 @@ void keyboard_process()
if (pcem_key[c] != oldkey[c])
{
oldkey[c] = pcem_key[c];
- if ( pcem_key[c] && scancodes[c].scancodes_make[0] == -1)
+ if ( pcem_key[c] && scancodes[c].scancodes_make[0] == 0)
continue;
- if (!pcem_key[c] && scancodes[c].scancodes_break[0] == -1)
+ if (!pcem_key[c] && scancodes[c].scancodes_break[0] == 0)
continue;
// pclog("Key %02X start\n", c);
d = 0;
if (pcem_key[c])
{
- while (scancodes[c].scancodes_make[d] != -1)
+ while (scancodes[c].scancodes_make[d] != 0)
keyboard_send(scancodes[c].scancodes_make[d++]);
}
else
{
- while (scancodes[c].scancodes_break[d] != -1)
+ while (scancodes[c].scancodes_break[d] != 0)
keyboard_send(scancodes[c].scancodes_break[d++]);
}
}
@@ -283,13 +453,32 @@ void keyboard_process()
if (keydelay[c] >= 30)
{
keydelay[c] -= 10;
- if (scancode_set1[c].scancodes_make[0] == -1)
+ if (scancodes[c].scancodes_make[0] == 0)
continue;
d = 0;
- while (scancode_set1[c].scancodes_make[d] != -1)
- keyboard_send(scancode_set1[c].scancodes_make[d++]);
+ while (scancodes[c].scancodes_make[d] != 0)
+ keyboard_send(scancodes[c].scancodes_make[d++]);
}
}
}
+
+void keyboard_send_scancode(int code, int is_break)
+{
+ scancode *scancodes = (AT || romset == ROM_XI8088) ? at_scancodes : scancode_xt;
+ int d = 0;
+
+ if (!keyboard_scan) return;
+
+ if (!is_break)
+ {
+ while (scancodes[code].scancodes_make[d] != 0)
+ keyboard_send(scancodes[code].scancodes_make[d++]);
+ }
+ else
+ {
+ while (scancodes[code].scancodes_break[d] != 0)
+ keyboard_send(scancodes[code].scancodes_break[d++]);
+ }
+}
diff --git a/src/keyboard.h b/src/keyboard.h
index 5d5283c..c4a63e0 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -3,4 +3,14 @@ extern void (*keyboard_poll)();
void keyboard_process();
extern int keyboard_scan;
-extern int pcem_key[272];
+extern uint8_t pcem_key[272];
+
+enum
+{
+ SCANCODE_SET_1,
+ SCANCODE_SET_2,
+ SCANCODE_SET_3
+};
+
+void keyboard_set_scancode_set(int set);
+void keyboard_send_scancode(int code, int is_break);
diff --git a/src/keyboard_at.c b/src/keyboard_at.c
index 2f06842..312326a 100644
--- a/src/keyboard_at.c
+++ b/src/keyboard_at.c
@@ -26,6 +26,8 @@
#define PS2_REFRESH_TIME (16 * TIMER_USEC)
+#define RESET_DELAY_TIME (100 * 10) /*600ms*/
+
struct
{
int initialised;
@@ -36,6 +38,10 @@ struct
uint8_t mem[0x20];
uint8_t out;
int out_new, out_delayed;
+
+ int scancode_set;
+ int translate;
+ int next_is_release;
uint8_t input_port;
uint8_t output_port;
@@ -54,17 +60,41 @@ struct
int is_ps2;
pc_timer_t send_delay_timer;
+
+ int reset_delay;
} keyboard_at;
+/*Translation table taken from https://www.win.tue.nl/~aeb/linux/kbd/scancodes-10.html#ss10.3*/
+static uint8_t at_translation[256] =
+{
+ 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
+ 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
+ 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
+ 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
+ 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
+ 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
+ 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
+ 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
+ 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
static uint8_t key_ctrl_queue[16];
static int key_ctrl_queue_start = 0, key_ctrl_queue_end = 0;
static uint8_t key_queue[16];
static int key_queue_start = 0, key_queue_end = 0;
-static uint8_t mouse_queue[16];
+uint8_t mouse_queue[16];
int mouse_queue_start = 0, mouse_queue_end = 0;
+void keyboard_at_adddata_keyboard(uint8_t val);
+
void keyboard_at_poll()
{
timer_advance_u64(&keyboard_at.send_delay_timer, (100 * TIMER_USEC));
@@ -74,15 +104,23 @@ void keyboard_at_poll()
keyboard_at.wantirq = 0;
if (keyboard_at.out_new & 0x100)
{
- if (keyboard_at.mem[0] & 0x02)
- picint(0x1000);
- keyboard_at.out = keyboard_at.out_new & 0xff;
- keyboard_at.out_new = -1;
- keyboard_at.status |= STAT_OFULL;
- keyboard_at.status &= ~STAT_IFULL;
- keyboard_at.status |= STAT_MFULL;
-// pclog("keyboard_at : take IRQ12\n");
- keyboard_at.last_irq = 0x1000;
+ if (mouse_scan)
+ {
+// pclog("keyboard_at : take IRQ12\n");
+ if (keyboard_at.mem[0] & 0x02)
+ picint(0x1000);
+ keyboard_at.out = keyboard_at.out_new & 0xff;
+ keyboard_at.out_new = -1;
+ keyboard_at.status |= STAT_OFULL;
+ keyboard_at.status &= ~STAT_IFULL;
+ keyboard_at.status |= STAT_MFULL;
+ keyboard_at.last_irq = 0x1000;
+ }
+ else
+ {
+// pclog("keyboard_at: suppressing IRQ12\n");
+ keyboard_at.out_new = -1;
+ }
}
else
{
@@ -121,13 +159,20 @@ void keyboard_at_poll()
{
keyboard_at.out_new = mouse_queue[mouse_queue_start] | 0x100;
mouse_queue_start = (mouse_queue_start + 1) & 0xf;
- }
+ }
else if (!(keyboard_at.status & STAT_OFULL) && keyboard_at.out_new == -1 &&
!(keyboard_at.mem[0] & 0x10) && key_queue_start != key_queue_end)
{
keyboard_at.out_new = key_queue[key_queue_start];
key_queue_start = (key_queue_start + 1) & 0xf;
- }
+ }
+
+ if (keyboard_at.reset_delay)
+ {
+ keyboard_at.reset_delay--;
+ if (!keyboard_at.reset_delay)
+ keyboard_at_adddata_keyboard(0xaa);
+ }
}
void keyboard_at_adddata(uint8_t val)
@@ -144,6 +189,8 @@ void keyboard_at_adddata(uint8_t val)
void keyboard_at_adddata_keyboard(uint8_t val)
{
+ if (keyboard_at.reset_delay)
+ return;
/* if (val == 0x1c)
{
key_1c++;
@@ -173,6 +220,21 @@ void keyboard_at_adddata_keyboard(uint8_t val)
case 0x4D: t3100e_notify_set(0x0F); break; /* Right */
}
}
+ if (keyboard_at.translate)
+ {
+ if (val == 0xf0)
+ {
+ keyboard_at.next_is_release = 1;
+ return;
+ }
+ else
+ {
+ val = at_translation[val];
+ if (keyboard_at.next_is_release)
+ val |= 0x80;
+ keyboard_at.next_is_release = 0;
+ }
+ }
key_queue[key_queue_end] = val;
key_queue_end = (key_queue_end + 1) & 0xf;
// pclog("keyboard_at : %02X added to key queue\n", val);
@@ -221,6 +283,7 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
if (!(val & 1) && keyboard_at.wantirq)
keyboard_at.wantirq = 0;
mouse_scan = !(val & 0x20);
+ keyboard_at.translate = val & 0x40;
}
break;
@@ -247,13 +310,22 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
keyboard_at.output_port = val;
break;
+ case 0xd2: /*Write to keyboard output buffer*/
+ keyboard_at_adddata(val);
+ break;
+
case 0xd3: /*Write to mouse output buffer*/
keyboard_at_adddata_mouse(val);
break;
case 0xd4: /*Write to mouse*/
if (keyboard_at.mouse_write)
+ {
keyboard_at.mouse_write(val, keyboard_at.mouse_p);
+ /*Implicitly enable mouse*/
+ mouse_scan = 1;
+ keyboard_at.mem[0] &= ~0x20;
+ }
break;
default:
@@ -274,6 +346,45 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
case 0xed: /*Set/reset LEDs*/
keyboard_at_adddata_keyboard(0xfa);
break;
+
+ case 0xf0: /*Set scancode set*/
+ switch (val)
+ {
+ case 0: /*Read current set*/
+ keyboard_at_adddata_keyboard(0xfa);
+ switch (keyboard_at.scancode_set)
+ {
+ case SCANCODE_SET_1:
+ keyboard_at_adddata_keyboard(0x01);
+ break;
+ case SCANCODE_SET_2:
+ keyboard_at_adddata_keyboard(0x02);
+ break;
+ case SCANCODE_SET_3:
+ keyboard_at_adddata_keyboard(0x03);
+ break;
+ }
+ break;
+ case 1:
+ keyboard_at.scancode_set = SCANCODE_SET_1;
+ keyboard_set_scancode_set(SCANCODE_SET_1);
+ keyboard_at_adddata_keyboard(0xfa);
+ break;
+ case 2:
+ keyboard_at.scancode_set = SCANCODE_SET_2;
+ keyboard_set_scancode_set(SCANCODE_SET_2);
+ keyboard_at_adddata_keyboard(0xfa);
+ break;
+ case 3:
+ keyboard_at.scancode_set = SCANCODE_SET_3;
+ keyboard_set_scancode_set(SCANCODE_SET_3);
+ keyboard_at_adddata_keyboard(0xfa);
+ break;
+ default:
+ keyboard_at_adddata_keyboard(0xfe);
+ break;
+ }
+ break;
case 0xf3: /*Set typematic rate/delay*/
keyboard_at_adddata_keyboard(0xfa);
@@ -299,10 +410,19 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
keyboard_at_adddata_keyboard(0xfa);
break;
+ case 0xee: /*Diagnostic echo*/
+ keyboard_at_adddata_keyboard(0xee);
+ break;
+
+ case 0xf0: /*Set scancode set*/
+ keyboard_at.key_wantdata = 1;
+ keyboard_at_adddata_keyboard(0xfa);
+ break;
+
case 0xf2: /*Read ID*/
keyboard_at_adddata_keyboard(0xfa);
keyboard_at_adddata_keyboard(0xab);
- keyboard_at_adddata_keyboard(0x41);
+ keyboard_at_adddata_keyboard(0x83);
break;
case 0xf3: /*Set typematic rate/delay*/
@@ -322,7 +442,7 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
case 0xff: /*Reset*/
key_queue_start = key_queue_end = 0; /*Clear key queue*/
keyboard_at_adddata_keyboard(0xfa);
- keyboard_at_adddata_keyboard(0xaa);
+ keyboard_at.reset_delay = RESET_DELAY_TIME;
break;
default:
@@ -387,10 +507,12 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
case 0xa7: /*Disable mouse port*/
mouse_scan = 0;
+ keyboard_at.mem[0] |= 0x20;
break;
case 0xa8: /*Enable mouse port*/
mouse_scan = 1;
+ keyboard_at.mem[0] &= ~0x20;
break;
case 0xa9: /*Test mouse port*/
@@ -404,9 +526,9 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
key_ctrl_queue_start = key_ctrl_queue_end = 0;
keyboard_at.status &= ~STAT_OFULL;
}
- /* T3100e expects STAT_IFULL to be set immediately
+ /* T3100e and Samsung SPC-6000A expects STAT_IFULL to be set immediately
* after sending 0xAA */
- if(romset == ROM_T3100E) keyboard_at.status |= STAT_IFULL;
+ if(romset == ROM_T3100E || romset == ROM_SPC6000A) keyboard_at.status |= STAT_IFULL;
keyboard_at.status |= STAT_SYSFLAG;
keyboard_at.mem[0] |= 0x04;
keyboard_at_adddata(0x55);
@@ -468,6 +590,11 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
keyboard_at.want60 = 1;
break;
+ case 0xba:
+ if (romset == ROM_ENDEAVOR || romset == ROM_ZAPPA || romset == ROM_ITAUTEC_INFOWAYM)
+ keyboard_at_adddata(0);
+ break;
+
/* T3100e commands not implemented:
* 0xB7: Emulate PS/2 keyboard
* 0xB8: Emulate AT keyboard */
@@ -498,7 +625,11 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
if (romset == ROM_T3100E)
keyboard_at.input_port = (t3100e_mono_get() & 1) ? 0xFF : 0xBF;
- keyboard_at_adddata(keyboard_at.input_port | 4);
+ if (romset == ROM_ENDEAVOR || romset == ROM_ZAPPA || romset == ROM_ITAUTEC_INFOWAYM)
+ keyboard_at_adddata(keyboard_at.input_port | 4 | 0x40);
+ else
+ keyboard_at_adddata(keyboard_at.input_port | 4);
+
keyboard_at.input_port = ((keyboard_at.input_port + 1) & 3) | (keyboard_at.input_port & 0xfc);
break;
@@ -506,7 +637,10 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
break;
case 0xca: /*AMI - read keyboard mode*/
- keyboard_at_adddata(0x00); /*ISA mode*/
+ if (romset == ROM_GA686BX) /*TODO*/
+ keyboard_at_adddata(0x01); /*PS2 mode*/
+ else
+ keyboard_at_adddata(0x00); /*ISA mode*/
break;
case 0xcb: /*AMI - set keyboard mode*/
@@ -525,6 +659,10 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
keyboard_at.want60 = 1;
break;
+ case 0xd2: /*Write keyboard output buffer*/
+ keyboard_at.want60 = 1;
+ break;
+
case 0xd3: /*Write mouse output buffer*/
keyboard_at.want60 = 1;
break;
@@ -536,6 +674,15 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
case 0xe0: /*Read test inputs*/
keyboard_at_adddata(0x00);
break;
+
+ // AWARD BIOS: called after turbo ON/OFF in the
+ // Hyundai Super-286TR and probably other AWARD 286
+ // bioses. Related to the Turbo LEDs. Exact function
+ // can't be confirmed because the system in question
+ // has no such leds.
+ //case 0xe8: /* Turbo ON, always followed by 0xba */
+ //case 0xe9: /* Turbo OFF */
+ //break;
case 0xef: /*??? - sent by AMI486*/
break;
@@ -560,6 +707,9 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
uint8_t keyboard_at_read(uint16_t port, void *priv)
{
uint8_t temp = 0xff;
+
+ if (romset != ROM_IBMAT && romset != ROM_IBMXT286)
+ cycles -= ISA_CYCLES(8);
// if (port != 0x61) pclog("keyboard_at : read %04X ", port);
if (romset == ROM_XI8088 && port == 0x63)
port = 0x61;
@@ -615,6 +765,7 @@ void keyboard_at_reset()
else
keyboard_at.input_port = (video_is_mda()) ? 0xf0 : 0xb0;
keyboard_at.out_new = -1;
+ keyboard_at.out_delayed = -1;
keyboard_at.last_irq = 0;
keyboard_at.key_wantdata = 0;
@@ -639,6 +790,8 @@ void keyboard_at_init()
keyboard_at.mouse_write = NULL;
keyboard_at.mouse_p = NULL;
keyboard_at.is_ps2 = 0;
+ keyboard_set_scancode_set(SCANCODE_SET_2);
+ keyboard_at.scancode_set = SCANCODE_SET_2;
timer_add(&keyboard_at.send_delay_timer, keyboard_at_poll, NULL, 1);
}
diff --git a/src/keyboard_at.h b/src/keyboard_at.h
index 6271e75..5dc00fa 100644
--- a/src/keyboard_at.h
+++ b/src/keyboard_at.h
@@ -5,5 +5,6 @@ void keyboard_at_poll();
void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p);
void keyboard_at_adddata_mouse(uint8_t val);
+extern uint8_t mouse_queue[16];
extern int mouse_queue_start, mouse_queue_end;
extern int mouse_scan;
diff --git a/src/keyboard_pcjr.c b/src/keyboard_pcjr.c
index c7119c2..6519897 100644
--- a/src/keyboard_pcjr.c
+++ b/src/keyboard_pcjr.c
@@ -1,5 +1,7 @@
#include "ibm.h"
#include "device.h"
+#include "cassette.h"
+#include "fdd.h"
#include "io.h"
#include "mem.h"
#include "nmi.h"
@@ -129,6 +131,8 @@ void keyboard_pcjr_write(uint16_t port, uint8_t val, void *priv)
timer_process();
+ cassette_set_motor((val & 8) ? 0 : 1);
+
speaker_update();
speaker_gated = val & 1;
speaker_enable = val & 2;
@@ -171,7 +175,12 @@ uint8_t keyboard_pcjr_read(uint16_t port, void *priv)
case 0x62:
temp = (keyboard_pcjr.latched ? 1 : 0);
temp |= 0x02; /*Modem card not installed*/
- temp |= (ppispeakon ? 0x10 : 0);
+ if (fdd_get_type(0) == 0)
+ temp |= 0x04; /*Disc card not installed*/
+ if (!(keyboard_pcjr.pb & 8))
+ temp |= (cassette_input()) ? 0x10 : 0;
+ else
+ temp |= (ppispeakon ? 0x10 : 0);
temp |= (ppispeakon ? 0x20 : 0);
temp |= (keyboard_pcjr.data ? 0x40: 0);
// temp |= 0x04;
diff --git a/src/keyboard_xt.c b/src/keyboard_xt.c
index d2bef2e..7f5c794 100644
--- a/src/keyboard_xt.c
+++ b/src/keyboard_xt.c
@@ -1,5 +1,6 @@
#include "ibm.h"
#include "device.h"
+#include "cassette.h"
#include "fdd.h"
#include "io.h"
#include "mem.h"
@@ -127,7 +128,9 @@ void keyboard_xt_write(uint16_t port, uint8_t val, void *priv)
timer_process();
- if (keyboard_xt.pb2_turbo)
+ if (romset == ROM_IBMPC)
+ cassette_set_motor((val & 8) ? 0 : 1);
+ else if (keyboard_xt.pb2_turbo)
cpu_set_turbo((val & 4) ? 0 : 1);
speaker_update();
@@ -154,7 +157,7 @@ uint8_t keyboard_xt_read(uint16_t port, void *priv)
switch (port)
{
case 0x60:
- if ((romset == ROM_IBMPC) && (keyboard_xt.pb & 0x80))
+ if ((romset == ROM_IBMPC || romset == ROM_LEDGE_MODELM) && (keyboard_xt.pb & 0x80))
{
if (video_is_ega_vga())
temp = 0x4D;
@@ -162,6 +165,8 @@ uint8_t keyboard_xt_read(uint16_t port, void *priv)
temp = 0x7D;
else
temp = 0x6D;
+ if (hasfpu)
+ temp |= 0x02;
}
else if ((romset == ROM_ATARIPC3) && (keyboard_xt.pb & 0x80))
{
@@ -184,6 +189,13 @@ uint8_t keyboard_xt_read(uint16_t port, void *priv)
temp = ((mem_size-64) / 32) & 0xf;
else
temp = ((mem_size-64) / 32) >> 4;
+
+ temp |= (cassette_input()) ? 0x10 : 0;
+ }
+ else if (romset == ROM_LEDGE_MODELM)
+ {
+ /*High bit of memory size is read from port 0xa0*/
+ temp = ((mem_size-64) / 32) & 0xf;
}
else if (romset == ROM_ATARIPC3)
{
@@ -204,7 +216,7 @@ uint8_t keyboard_xt_read(uint16_t port, void *priv)
temp = 6;
}
else
- temp = 0xD;
+ temp = hasfpu ? 0xf : 0xd;
}
temp |= (ppispeakon ? 0x20 : 0);
if (keyboard_xt.tandy)
@@ -220,6 +232,16 @@ uint8_t keyboard_xt_read(uint16_t port, void *priv)
return temp;
}
+static uint8_t ledge_modelm_read(uint16_t port, void *p)
+{
+ uint8_t temp = 0;
+
+ if (((mem_size-64) / 32) >> 4)
+ temp |= 0x40;
+
+ return temp;
+}
+
void keyboard_xt_reset()
{
keyboard_xt.wantirq = 0;
@@ -231,6 +253,8 @@ void keyboard_xt_init()
{
//return;
io_sethandler(0x0060, 0x0004, keyboard_xt_read, NULL, NULL, keyboard_xt_write, NULL, NULL, NULL);
+ if (romset == ROM_LEDGE_MODELM)
+ io_sethandler(0x00a0, 0x0001, ledge_modelm_read, NULL, NULL, NULL, NULL, NULL, NULL);
keyboard_xt_reset();
keyboard_send = keyboard_xt_adddata;
keyboard_poll = keyboard_xt_poll;
diff --git a/src/laserxt.c b/src/laserxt.c
index 361ced7..5d15034 100644
--- a/src/laserxt.c
+++ b/src/laserxt.c
@@ -1,5 +1,6 @@
/*This is the chipset used in the LaserXT series model*/
#include "ibm.h"
+#include "cpu.h"
#include "io.h"
#include "mem.h"
@@ -7,6 +8,7 @@ static int laserxt_emspage[4];
static int laserxt_emscontrol[4];
static mem_mapping_t laserxt_ems_mapping[4];
static int laserxt_ems_baseaddr_index = 0;
+static uint8_t laserxt_turbo = 0x80;
static uint32_t get_laserxt_ems_addr(uint32_t addr)
{
@@ -25,6 +27,11 @@ static void laserxt_write(uint16_t port, uint8_t val, void *priv)
switch (port)
{
+ case 0x01F0:
+ laserxt_turbo = val;
+ cpu_set_turbo((val & 0x80) >> 7);
+ //pclog("Turbo %s at %04X:%04X\n", (val & 0x80) ? "Enabled" : "Disabled", CS, cpu_state.oldpc);
+ break;
case 0x0208: case 0x4208: case 0x8208: case 0xC208:
laserxt_emspage[port >> 14] = val;
paddr = 0xC0000 + (port & 0xC000) + (((laserxt_ems_baseaddr_index + (4 - (port >> 14))) & 0x0C) << 14);
@@ -64,6 +71,9 @@ static uint8_t laserxt_read(uint16_t port, void *priv)
{
switch (port)
{
+ case 0x01F0:
+ return laserxt_turbo;
+
case 0x0208: case 0x4208: case 0x8208: case 0xC208:
return laserxt_emspage[port >> 14];
@@ -95,6 +105,10 @@ void laserxt_init()
{
int i;
+ io_sethandler(0x01F0, 0x0001, laserxt_read, NULL, NULL, laserxt_write, NULL, NULL, NULL);
+ laserxt_turbo = 0x80;
+ cpu_set_turbo(1);
+
if (mem_size > 640)
{
io_sethandler(0x0208, 0x0002, laserxt_read, NULL, NULL, laserxt_write, NULL, NULL, NULL);
@@ -111,5 +125,5 @@ void laserxt_init()
mem_mapping_add(&laserxt_ems_mapping[i], 0xE0000 + (i << 14), 0x4000, mem_read_laserxtems, NULL, NULL, mem_write_laserxtems, NULL, NULL, ram + 0xA0000 + (i << 14), 0, NULL);
mem_mapping_disable(&laserxt_ems_mapping[i]);
}
- mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ mem_set_mem_state(0x0a0000, 0x60000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
diff --git a/src/mca.c b/src/mca.c
index ebd8ccb..11f8268 100644
--- a/src/mca.c
+++ b/src/mca.c
@@ -6,6 +6,7 @@
void (*mca_card_write[8])(int addr, uint8_t val, void *priv);
uint8_t (*mca_card_read[8])(int addr, void *priv);
+void (*mca_card_reset[8])(void *priv);
void *mca_priv[8];
static int mca_index;
static int mca_nr_cards;
@@ -14,10 +15,13 @@ void mca_init(int nr_cards)
{
int c;
+ MCA = 1;
+
for (c = 0; c < 8; c++)
{
mca_card_read[c] = NULL;
mca_card_write[c] = NULL;
+ mca_card_reset[c] = NULL;
mca_priv[c] = NULL;
}
@@ -47,7 +51,18 @@ void mca_write(uint16_t port, uint8_t val)
mca_card_write[mca_index](port, val, mca_priv[mca_index]);
}
-void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void *priv)
+void mca_reset(void)
+{
+ int c;
+
+ for (c = 0; c < 8; c++)
+ {
+ if (mca_card_reset[c])
+ mca_card_reset[c](mca_priv[c]);
+ }
+}
+
+void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void (*reset)(void *priv), void *priv)
{
int c;
@@ -57,6 +72,7 @@ void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint
{
mca_card_read[c] = read;
mca_card_write[c] = write;
+ mca_card_reset[c] = reset;
mca_priv[c] = priv;
return;
}
diff --git a/src/mca.h b/src/mca.h
index cf9361f..a298d24 100644
--- a/src/mca.h
+++ b/src/mca.h
@@ -1,5 +1,6 @@
void mca_init(int nr_cards);
-void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void *priv);
+void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void (*reset)(void *priv), void *priv);
void mca_set_index(int index);
uint8_t mca_read(uint16_t port);
void mca_write(uint16_t port, uint8_t val);
+void mca_reset(void);
diff --git a/src/mem.c b/src/mem.c
index dd3186d..15dc5ee 100644
--- a/src/mem.c
+++ b/src/mem.c
@@ -33,7 +33,7 @@ mem_mapping_t ram_high_mapping;
mem_mapping_t ram_mid_mapping;
mem_mapping_t ram_remapped_mapping;
mem_mapping_t bios_mapping[8];
-mem_mapping_t bios_high_mapping[8];
+mem_mapping_t bios_high_mapping[9];
static mem_mapping_t romext_mapping;
static uint8_t ff_array[0x1000];
@@ -51,9 +51,19 @@ uint64_t *byte_code_present_mask;
uint32_t mem_logical_addr;
+void (*smram_enable)(void);
+void (*smram_disable)(void);
+
int mmuflush=0;
int mmu_perm=4;
+int mem_addr_is_ram(uint32_t addr)
+{
+ mem_mapping_t *mapping = read_mapping[addr >> 14];
+
+ return (mapping == &ram_low_mapping) || (mapping == &ram_high_mapping) || (mapping == &ram_mid_mapping) || (mapping == &ram_remapped_mapping);
+}
+
void resetreadlookup()
{
int c;
@@ -1336,24 +1346,26 @@ void mem_add_bios()
{
if (AT || (romset == ROM_XI8088 && xi8088_bios_128kb()))
{
- mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
- mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x4000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
- mem_mapping_add(&bios_mapping[2], 0xe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x8000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
- mem_mapping_add(&bios_mapping[3], 0xec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0xc000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x20000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x24000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_mapping[2], 0xe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x28000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_mapping[3], 0xec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x2c000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
}
- mem_mapping_add(&bios_mapping[4], 0xf0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x10000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
- mem_mapping_add(&bios_mapping[5], 0xf4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x14000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
- mem_mapping_add(&bios_mapping[6], 0xf8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x18000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
- mem_mapping_add(&bios_mapping[7], 0xfc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x1c000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_mapping[4], 0xf0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x30000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_mapping[5], 0xf4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x34000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_mapping[6], 0xf8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x38000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_mapping[7], 0xfc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x3c000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0);
- mem_mapping_add(&bios_high_mapping[0], (AT && cpu_16bitbus) ? 0xfe0000 : 0xfffe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom, MEM_MAPPING_ROM, 0);
- mem_mapping_add(&bios_high_mapping[1], (AT && cpu_16bitbus) ? 0xfe4000 : 0xfffe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x4000 & biosmask), MEM_MAPPING_ROM, 0);
- mem_mapping_add(&bios_high_mapping[2], (AT && cpu_16bitbus) ? 0xfe8000 : 0xfffe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x8000 & biosmask), MEM_MAPPING_ROM, 0);
- mem_mapping_add(&bios_high_mapping[3], (AT && cpu_16bitbus) ? 0xfec000 : 0xfffec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0xc000 & biosmask), MEM_MAPPING_ROM, 0);
- mem_mapping_add(&bios_high_mapping[4], (AT && cpu_16bitbus) ? 0xff0000 : 0xffff0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x10000 & biosmask), MEM_MAPPING_ROM, 0);
- mem_mapping_add(&bios_high_mapping[5], (AT && cpu_16bitbus) ? 0xff4000 : 0xffff4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x14000 & biosmask), MEM_MAPPING_ROM, 0);
- mem_mapping_add(&bios_high_mapping[6], (AT && cpu_16bitbus) ? 0xff8000 : 0xffff8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x18000 & biosmask), MEM_MAPPING_ROM, 0);
- mem_mapping_add(&bios_high_mapping[7], (AT && cpu_16bitbus) ? 0xffc000 : 0xffffc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x1c000 & biosmask), MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_high_mapping[0], (AT && cpu_16bitbus) ? 0xfe0000 : 0xfffe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x20000 & biosmask), MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_high_mapping[1], (AT && cpu_16bitbus) ? 0xfe4000 : 0xfffe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x24000 & biosmask), MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_high_mapping[2], (AT && cpu_16bitbus) ? 0xfe8000 : 0xfffe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x28000 & biosmask), MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_high_mapping[3], (AT && cpu_16bitbus) ? 0xfec000 : 0xfffec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x2c000 & biosmask), MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_high_mapping[4], (AT && cpu_16bitbus) ? 0xff0000 : 0xffff0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x30000 & biosmask), MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_high_mapping[5], (AT && cpu_16bitbus) ? 0xff4000 : 0xffff4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x34000 & biosmask), MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_high_mapping[6], (AT && cpu_16bitbus) ? 0xff8000 : 0xffff8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x38000 & biosmask), MEM_MAPPING_ROM, 0);
+ mem_mapping_add(&bios_high_mapping[7], (AT && cpu_16bitbus) ? 0xffc000 : 0xffffc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x3c000 & biosmask), MEM_MAPPING_ROM, 0);
+ if (biosmask == 0x3ffff)
+ mem_mapping_add(&bios_high_mapping[8], (AT && cpu_16bitbus) ? 0xfc0000 : 0xfffc0000, 0x20000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom, MEM_MAPPING_ROM, 0);
}
int mem_a20_key = 0, mem_a20_alt = 0;
@@ -1374,10 +1386,14 @@ static void mem_remap_top(int max_size)
for (c = ((start * 1024) >> 12); c < (((start + size) * 1024) >> 12); c++)
{
- pages[c].mem = &ram[0xA0000 + ((c - ((start * 1024) >> 12)) << 12)];
+ int offset = c - ((start * 1024) >> 12);
+ pages[c].mem = &ram[0xA0000 + (offset << 12)];
pages[c].write_b = mem_write_ramb_page;
pages[c].write_w = mem_write_ramw_page;
pages[c].write_l = mem_write_raml_page;
+ pages[c].evict_prev = EVICT_NOT_IN_LIST;
+ pages[c].byte_dirty_mask = &byte_dirty_mask[offset * 64];
+ pages[c].byte_code_present_mask = &byte_code_present_mask[offset * 64];
}
mem_set_mem_state(start * 1024, size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
@@ -1407,6 +1423,9 @@ void mem_init()
page_lookup = malloc((1 << 20) * sizeof(page_t *));
memset(ff_array, 0xff, sizeof(ff_array));
+
+ smram_enable = NULL;
+ smram_disable = NULL;
}
void mem_alloc()
@@ -1449,7 +1468,22 @@ void mem_alloc()
memset(_mem_state, 0, sizeof(_mem_state));
mem_set_mem_state(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
- mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ if (romset == ROM_XI8088)
+ {
+ // Xi 8088 UMBs are selected by DIP Switches
+ mem_set_mem_state(0x0a0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ mem_set_mem_state(0x0c0000, 0x08000, model_get_config_int("umb_c0000h_c7fff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL));
+ mem_set_mem_state(0x0c8000, 0x08000, model_get_config_int("umb_c8000h_cffff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL));
+ mem_set_mem_state(0x0d0000, 0x08000, model_get_config_int("umb_d0000h_d7fff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL));
+ mem_set_mem_state(0x0d8000, 0x08000, model_get_config_int("umb_d8000h_dffff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL));
+ mem_set_mem_state(0x0e0000, 0x08000, model_get_config_int("umb_e0000h_e7fff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL));
+ mem_set_mem_state(0x0e8000, 0x08000, model_get_config_int("umb_e8000h_effff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL));
+ mem_set_mem_state(0x0f0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ }
+ else
+ {
+ mem_set_mem_state(0x0a0000, 0x60000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ }
mem_mapping_add(&ram_low_mapping, 0x00000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram, MEM_MAPPING_INTERNAL, NULL);
if (mem_size > 1024)
@@ -1465,8 +1499,8 @@ void mem_alloc()
mem_mapping_add(&ram_high_mapping, 0x100000, ((mem_size - 1024) * 1024), mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0x100000, MEM_MAPPING_INTERNAL, NULL);
}
}
- if (mem_size > 768)
- mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL);
+ if (mem_size > 768) // 640k - 768k is graphics RAM
+ mem_mapping_add(&ram_mid_mapping, 0xa0000, 0x60000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL);
if (romset == ROM_IBMPS1_2011)
mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL);
@@ -1475,6 +1509,9 @@ void mem_alloc()
mem_a20_key = 2;
mem_a20_alt = 0;
mem_a20_recalc();
+
+ purgable_page_list_head = 0;
+ purgeable_page_count = 0;
}
void mem_reset_page_blocks()
diff --git a/src/mem.h b/src/mem.h
index 429973a..bd733e7 100644
--- a/src/mem.h
+++ b/src/mem.h
@@ -107,7 +107,7 @@ void mem_write_nulll(uint32_t addr, uint32_t val, void *p);
FILE *romfopen(char *fn, char *mode);
mem_mapping_t bios_mapping[8];
-mem_mapping_t bios_high_mapping[8];
+mem_mapping_t bios_high_mapping[9];
extern mem_mapping_t ram_high_mapping;
extern mem_mapping_t ram_remapped_mapping;
@@ -153,6 +153,8 @@ static inline int page_in_evict_list(page_t *p)
void page_remove_from_evict_list(page_t *p);
void page_add_to_evict_list(page_t *p);
+int mem_addr_is_ram(uint32_t addr);
+
uint32_t mmutranslate_noabrt(uint32_t addr, int rw);
extern uint32_t get_phys_virt,get_phys_phys;
static inline uint32_t get_phys(uint32_t addr)
@@ -173,7 +175,7 @@ static inline uint32_t get_phys(uint32_t addr)
else
{
get_phys_phys = (mmutranslatereal(addr, 0) & rammask) & ~0xfff;
- if (!cpu_state.abrt)
+ if (!cpu_state.abrt && mem_addr_is_ram(get_phys_phys))
addreadlookup(get_phys_virt, get_phys_phys);
}
@@ -192,7 +194,7 @@ static inline uint32_t get_phys_noabrt(uint32_t addr)
return ((uintptr_t)readlookup2[addr >> 12] + addr) - (uintptr_t)ram;
phys_addr = mmutranslate_noabrt(addr, 0) & rammask;
- if (phys_addr != 0xffffffff)
+ if (phys_addr != 0xffffffff && mem_addr_is_ram(phys_addr))
addreadlookup(addr, phys_addr);
return phys_addr;
@@ -234,4 +236,7 @@ void mmu_invalidate(uint32_t addr);
int loadbios();
extern int purgeable_page_count;
+
+extern void (*smram_enable)(void);
+extern void (*smram_disable)(void);
#endif
diff --git a/src/mem_bios.c b/src/mem_bios.c
index c4229c5..2b6b174 100644
--- a/src/mem_bios.c
+++ b/src/mem_bios.c
@@ -19,7 +19,7 @@ static int mem_load_basic(char *path)
{
char s[256];
FILE *f;
-
+
sprintf(s, "%s/ibm-basic-1.10.rom", path);
f = romfopen(s, "rb");
if (!f)
@@ -53,25 +53,26 @@ static int mem_load_basic(char *path)
return 1;
}
-
+
int loadbios()
{
FILE *f=NULL,*ff=NULL;
int c;
-
- loadfont("mda.rom", 0);
- loadfont("wy700.rom", 3);
- loadfont("8x12.bin", 4);
-
+
+ loadfont("mda.rom", FONT_MDA);
+ loadfont("wy700.rom", FONT_WY700);
+ loadfont("8x12.bin", FONT_MDSI);
+ loadfont("im1024font.bin", FONT_IM1024);
+
biosmask = 0xffff;
-
+
if (!rom)
- rom = malloc(0x20000);
+ rom = malloc(0x40000);
memset(romext,0x63,0x4000);
memset(rom, 0xff, 0x20000);
-
+
pclog("Starting with romset %i\n", romset);
-
+
switch (romset)
{
case ROM_PC1512:
@@ -85,7 +86,7 @@ int loadbios()
}
fclose(ff);
fclose(f);
- loadfont("pc1512/40078.ic127", 2);
+ loadfont("pc1512/40078.ic127", FONT_CGA);
return 1;
case ROM_PC1640:
f=romfopen("pc1640/40044.v3","rb");
@@ -113,7 +114,20 @@ int loadbios()
}
fclose(ff);
fclose(f);
- loadfont("pc200/40109.bin", 1);
+ loadfont("pc200/40109.bin", FONT_PC200);
+ return 1;
+ case ROM_PPC512:
+ f=romfopen("ppc512/40107.v2","rb");
+ ff=romfopen("ppc512/40108.v2","rb");
+ if (!f || !ff) break;
+ for (c=0xC000;c<0x10000;c+=2)
+ {
+ rom[c]=getc(f);
+ rom[c+1]=getc(ff);
+ }
+ fclose(ff);
+ fclose(f);
+ loadfont("ppc512/40109.bin", FONT_PC200);
return 1;
case ROM_TANDY:
f=romfopen("tandy/tandy1t1.020","rb");
@@ -170,14 +184,14 @@ int loadbios()
return 1;
}
break;
-
+
case ROM_IBMPCJR:
f = romfopen("ibmpcjr/bios.rom","rb");
if (!f) break;
romfread(rom, 0x10000, 1, f);
fclose(f);
return 1;
-
+
case ROM_GENXT:
f=romfopen("genxt/pcxt.rom","rb");
if (!f) break;
@@ -204,7 +218,7 @@ int loadbios()
fclose(ff);
fclose(f);
return 1;
-
+
case ROM_PC2086:
f = romfopen("pc2086/40179.ic129" ,"rb");
ff = romfopen("pc2086/40180.ic132","rb");
@@ -232,9 +246,17 @@ int loadbios()
f = romfopen("pc3086/c000.bin", "rb");
if (!f) break;
fclose(f);
- biosmask = 0x3fff;
+ biosmask = 0x3fff;
return 1;
+ case ROM_PC5086:
+ f = romfopen("pc5086/sys_rom.bin" ,"rb");
+ if (!f) break;
+ romfread(rom, 65536, 1, f);
+ fclose(f);
+ return 1;
+
+
case ROM_IBMAT:
/* f=romfopen("amic206.bin","rb");
if (!f) break;
@@ -284,6 +306,17 @@ int loadbios()
romfread(rom,65536,1,f);
fclose(f);
return 1;*/
+ case ROM_AMA932J:
+// f=romfopen("at386/at386.bin","rb");
+ f=romfopen("ama932j/ami.bin","rb");
+ if (!f) break;
+ romfread(rom,65536,1,f);
+ fclose(f);
+ f=romfopen("ama932j/oti067.bin","rb");
+ if (!f) break;
+ fclose(f);
+ return 1;
+
case ROM_AMI386SX:
// f=romfopen("at386/at386.bin","rb");
f=romfopen("ami386/ami386.bin","rb");
@@ -332,6 +365,14 @@ int loadbios()
// memset(romext,0x63,0x8000);
return 1;
+ case ROM_TG286M:
+ f=romfopen("tg286m/ami.bin","rb");
+ if (!f) break;
+ romfread(rom,65536,1,f);
+ fclose(f);
+// memset(romext,0x63,0x8000);
+ return 1;
+
case ROM_AWARD286:
f=romfopen("award286/award.bin","rb");
if (!f) break;
@@ -339,6 +380,20 @@ int loadbios()
fclose(f);
return 1;
+ case ROM_GDC212M:
+ f=romfopen("gdc212m/gdc212m_72h.bin","rb");
+ if (!f) break;
+ romfread(rom,65536,1,f);
+ fclose(f);
+ return 1;
+
+ case ROM_HYUNDAI_SUPER286TR:
+ f=romfopen("super286tr/award.bin","rb");
+ if (!f) break;
+ romfread(rom,65536,1,f);
+ fclose(f);
+ return 1;
+
case ROM_GW286CT:
f=romfopen("gw286ct/2ctc001.bin","rb");
if (!f) break;
@@ -378,6 +433,58 @@ int loadbios()
}
break;
+ case ROM_SPC4620P:
+ f=romfopen("spc4620p/svb6120a_font.rom","rb");
+ if (!f) break;
+ fclose(f);
+ f = romfopen("spc4620p/31005h.u8", "rb");
+ ff = romfopen("spc4620p/31005h.u10","rb");
+ if (f && ff)
+ {
+ fseek(f, 0x8000, SEEK_SET);
+ fseek(ff, 0x8000, SEEK_SET);
+ for (c = 0x0000; c < 0x10000; c += 2)
+ {
+ rom[c] = getc(f);
+ rom[c + 1] = getc(ff);
+ }
+ fclose(ff);
+ fclose(f);
+ return 1;
+ }
+ break;
+
+ case ROM_SPC6000A:
+ f = romfopen("spc6000a/3c80.u27", "rb");
+ ff = romfopen("spc6000a/9f80.u26","rb");
+ if (f && ff)
+ {
+ for (c = 0x8000; c < 0x10000; c += 2)
+ {
+ rom[c] = getc(f);
+ rom[c + 1] = getc(ff);
+ }
+ fclose(ff);
+ fclose(f);
+ return 1;
+ }
+ break;
+
+ case ROM_SPC6033P:
+ f=romfopen("spc6033p/svb6120a_font.rom","rb");
+ if (!f) break;
+ fclose(f);
+ f=romfopen("spc6033p/phoenix.bin","rb");
+ if (f)
+ {
+ fseek(f, 0x10000, SEEK_SET);
+ romfread(rom,65536,1,f);
+
+ fclose(f);
+ return 1;
+ }
+ break;
+
case ROM_EUROPC:
// return 0;
f=romfopen("europc/50145","rb");
@@ -402,7 +509,7 @@ int loadbios()
ff = romfopen("megapc/211253-bios hi.u19", "rb");
if (!f || !ff) break;
fseek(f, 0x8000, SEEK_SET);
- fseek(ff, 0x8000, SEEK_SET);
+ fseek(ff, 0x8000, SEEK_SET);
for (c = 0x0000; c < 0x10000; c+=2)
{
rom[c]=getc(f);
@@ -411,7 +518,7 @@ int loadbios()
fclose(ff);
fclose(f);
return 1;
-
+
case ROM_AMI486:
f=romfopen("ami486/ami486.bin","rb");
if (!f) break;
@@ -419,7 +526,7 @@ int loadbios()
fclose(f);
//is486=1;
return 1;
-
+
case ROM_WIN486:
// f=romfopen("win486/win486.bin","rb");
f=romfopen("win486/ali1429g.amw","rb");
@@ -430,9 +537,9 @@ int loadbios()
return 1;
case ROM_PCI486:
- f=romfopen("hot-433/hot-433.ami","rb");
+ f=romfopen("hot-433/hot-433.ami","rb");
if (!f) break;
- romfread(rom, 0x20000, 1, f);
+ romfread(rom, 0x20000, 1, f);
fclose(f);
biosmask = 0x1ffff;
//is486=1;
@@ -441,34 +548,58 @@ int loadbios()
case ROM_SIS496:
f = romfopen("sis496/sis496-1.awa", "rb");
if (!f) break;
- romfread(rom, 0x20000, 1, f);
+ romfread(rom, 0x20000, 1, f);
fclose(f);
biosmask = 0x1ffff;
pclog("Load SIS496 %x %x\n", rom[0x1fff0], rom[0xfff0]);
return 1;
-
+
+ case ROM_P55VA:
+ f = romfopen("p55va/va021297.bin", "rb");
+ if (!f) break;
+ romfread(rom, 0x20000, 1, f);
+ fclose(f);
+ biosmask = 0x1ffff;
+ return 1;
+
+ case ROM_P55TVP4:
+ f = romfopen("p55tvp4/tv5i0204.awd", "rb");
+ if (!f) break;
+ romfread(rom, 0x20000, 1, f);
+ fclose(f);
+ biosmask = 0x1ffff;
+ return 1;
+
case ROM_430VX:
// f = romfopen("430vx/ga586atv.bin", "rb");
// f = fopen("430vx/vx29.bin", "rb");
f = romfopen("430vx/55xwuq0e.bin", "rb");
-// f=romfopen("430vx/430vx","rb");
+// f=romfopen("430vx/430vx","rb");
if (!f) break;
- romfread(rom, 0x20000, 1, f);
+ romfread(rom, 0x20000, 1, f);
fclose(f);
biosmask = 0x1ffff;
//is486=1;
return 1;
+ case ROM_P55T2P4:
+ f = romfopen("p55t2p4/0207_j2.bin", "rb");
+ if (!f) break;
+ romfread(rom, 0x20000, 1, f);
+ fclose(f);
+ biosmask = 0x1ffff;
+ return 1;
+
case ROM_REVENGE:
f = romfopen("revenge/1009af2_.bio", "rb");
if (!f) break;
fseek(f, 0x80, SEEK_SET);
- romfread(rom + 0x10000, 0x10000, 1, f);
+ romfread(rom + 0x10000, 0x10000, 1, f);
fclose(f);
f = romfopen("revenge/1009af2_.bi1", "rb");
if (!f) break;
fseek(f, 0x80, SEEK_SET);
- romfread(rom, 0xc000, 1, f);
+ romfread(rom, 0xc000, 1, f);
fclose(f);
biosmask = 0x1ffff;
//is486=1;
@@ -477,7 +608,7 @@ int loadbios()
f = romfopen("endeavor/1006cb0_.bio", "rb");
if (!f) break;
fseek(f, 0x80, SEEK_SET);
- romfread(rom + 0x10000, 0x10000, 1, f);
+ romfread(rom + 0x10000, 0x10000, 1, f);
fclose(f);
f = romfopen("endeavor/1006cb0_.bi1", "rb");
if (!f) break;
@@ -507,7 +638,7 @@ int loadbios()
f = romfopen("ibmps1es/f80000.bin", "rb");
if (!f) break;
fseek(f, 0x60000, SEEK_SET);
- romfread(rom, 0x20000, 1, f);
+ romfread(rom, 0x20000, 1, f);
fclose(f);
//#endif
biosmask = 0x1ffff;
@@ -517,7 +648,7 @@ int loadbios()
f = romfopen("ibmps1_2121/fc0000.bin", "rb");
if (!f) break;
fseek(f, 0x20000, SEEK_SET);
- romfread(rom, 0x20000, 1, f);
+ romfread(rom, 0x20000, 1, f);
fclose(f);
biosmask = 0x1ffff;
return 1;
@@ -542,7 +673,7 @@ int loadbios()
romfread(rom + 0xE000, 8192, 1, f);
fclose(f);
return 1;
-
+
case ROM_LTXT:
f = romfopen("ltxt/27c64.bin", "rb");
if (!f) break;
@@ -594,11 +725,11 @@ int loadbios()
romfread(rom + 0xE000, 8192, 1, f);
fclose(f);
return 1;
-
+
case ROM_IBMPS2_M30_286:
f = romfopen("ibmps2_m30_286/33f5381a.bin", "rb");
if (!f) break;
- romfread(rom, 0x20000, 1, f);
+ romfread(rom, 0x20000, 1, f);
fclose(f);
biosmask = 0x1ffff;
return 1;
@@ -654,7 +785,7 @@ int loadbios()
fclose(f);
biosmask = 0x1ffff;
return 1;
-
+
case ROM_ATARIPC3:
f=romfopen("ataripc3/AWARD_ATARI_PC_BIOS_3.08.BIN","rb");
if (!f) break;
@@ -674,7 +805,7 @@ int loadbios()
fclose(ff);
fclose(f);
return 1;
-
+
case ROM_EPSON_PCAX:
f = romfopen("epson_pcax/EVAX", "rb");
ff = romfopen("epson_pcax/ODAX", "rb");
@@ -701,7 +832,7 @@ int loadbios()
fclose(ff);
fclose(f);
return 1;
-
+
case ROM_EPSON_PCAX3:
f = romfopen("epson_pcax3/EVAX3", "rb");
ff = romfopen("epson_pcax3/ODAX3", "rb");
@@ -714,9 +845,9 @@ int loadbios()
fclose(ff);
fclose(f);
return 1;
-
+
case ROM_T3100E:
- loadfont("t3100e/t3100e_font.bin", 5);
+ loadfont("t3100e/t3100e_font.bin", FONT_T3100E);
f=romfopen("t3100e/t3100e.rom","rb");
if (!f) break;
romfread(rom,65536,1,f);
@@ -724,7 +855,7 @@ int loadbios()
return 1;
case ROM_T1000:
- loadfont("t1000/t1000font.rom", 2);
+ loadfont("t1000/t1000font.rom", FONT_CGA);
f=romfopen("t1000/t1000.rom","rb");
if (!f) break;
romfread(rom, 0x8000,1,f);
@@ -734,7 +865,7 @@ int loadbios()
return 1;
case ROM_T1200:
- loadfont("t1200/t1000font.rom", 2);
+ loadfont("t1200/t1000font.rom", FONT_CGA);
f=romfopen("t1200/t1200_019e.ic15.bin","rb");
if (!f) break;
romfread(rom, 0x8000,1,f);
@@ -742,14 +873,14 @@ int loadbios()
biosmask = 0x7fff;
fclose(f);
return 1;
-
+
case ROM_PB_L300SX:
f = romfopen("pb_l300sx/pb_l300sx.bin", "rb");
if (!f) break;
romfread(rom, 65536, 1, f);
fclose(f);
return 1;
-
+
case ROM_NCR_PC4I:
f=romfopen("ncr_pc4i/NCR_PC4i_BIOSROM_1985.BIN" ,"rb");
if (!f) break;
@@ -757,14 +888,14 @@ int loadbios()
fclose(f);
biosmask = 0x3fff;
return 1;
-
+
case ROM_TO16_PC:
f=romfopen("to16_pc/TO16_103.bin","rb");
if (!f) break;
romfread(rom+0x8000,32768,1,f);
fclose(f);
return 1;
-
+
case ROM_COMPAQ_PII:
f = romfopen("compaq_pii/109740-001.rom", "rb");
ff = romfopen("compaq_pii/109739-001.rom", "rb");
@@ -778,7 +909,7 @@ int loadbios()
fclose(f);
biosmask = 0x7fff;
return 1;
-
+
case ROM_ELX_PC425X:
/*PC-425X uses a single ROM chip containing both main and video BIOSes.
First 32kb is video BIOS, next 32kb is blank, last 64kb is main BIOS.
@@ -804,7 +935,7 @@ int loadbios()
f = romfopen("pb570/1007by0r.bio", "rb");
if (!f) break;
fseek(f, 0x80, SEEK_SET);
- romfread(rom + 0x10000, 0x10000, 1, f);
+ romfread(rom + 0x10000, 0x10000, 1, f);
fclose(f);
f = romfopen("pb570/1007by0r.bi1", "rb");
if (!f) break;
@@ -814,7 +945,7 @@ int loadbios()
fclose(f);
biosmask = 0x1ffff;
return 1;
-
+
case ROM_ZAPPA:
f = romfopen("zappa/1006bs0_.bio", "rb");
if (!f) break;
@@ -829,13 +960,31 @@ int loadbios()
biosmask = 0x1ffff;
return 1;
+ // keep separate from generic Zappa because there is a BIOS logo
+ // in flash.bin
+ case ROM_ITAUTEC_INFOWAYM:
+// if (!rom_present("infowaym/gd5434.bin"))
+// break;
+ f = romfopen("infowaym/1006bs0_.bio", "rb");
+ if (!f) break;
+ fseek(f, 0x80, SEEK_SET);
+ romfread(rom + 0x10000, 0x10000, 1, f);
+ fclose(f);
+ f = romfopen("infowaym/1006bs0_.bi1", "rb");
+ if (!f) break;
+ fseek(f, 0x80, SEEK_SET);
+ romfread(rom, 0xd000, 1, f);
+ fclose(f);
+ biosmask = 0x1ffff;
+ return 1;
+
case ROM_PB520R:
if (!rom_present("pb520r/gd5434.bin"))
break;
f = romfopen("pb520r/1009bc0r.bio", "rb");
if (!f) break;
fseek(f, 0x80, SEEK_SET);
- romfread(rom + 0x10000, 0x10000, 1, f);
+ romfread(rom + 0x10000, 0x10000, 1, f);
fclose(f);
f = romfopen("pb520r/1009bc0r.bi1", "rb");
if (!f) break;
@@ -845,7 +994,7 @@ int loadbios()
fclose(f);
biosmask = 0x1ffff;
return 1;
-
+
case ROM_COMPAQ_PIP:
f=romfopen("compaq_pip/Compaq Portable Plus 100666-001 Rev C.bin","rb");
if (!f) break;
@@ -901,6 +1050,49 @@ int loadbios()
biosmask = 0x1ffff;
return 1;
+ case ROM_TULIP_TC7:
+ f = romfopen("tulip_tc7/tc7be.bin", "rb");
+ ff = romfopen("tulip_tc7/tc7bo.bin", "rb");
+ if (!f || !ff) break;
+ for (c = 0x0000; c < 0x8000; c += 2)
+ {
+ rom[c] = getc(f);
+ rom[c + 1] = getc(ff);
+ }
+ fclose(ff);
+ fclose(f);
+ biosmask = 0x7fff;
+ return 1;
+
+ case ROM_ZD_SUPERS: /* [8088] Zenith Data Systems SupersPort */
+ f=romfopen("zdsupers/z184m v3.1d.10d","rb");
+ if (!f) break;
+ romfread(rom, 32768, 1, f);
+ fclose(f);
+ biosmask = 0x7fff;
+ return 1;
+
+ case ROM_PB410A:
+ f = romfopen("pb410a/PB410A.080337.4ABF.U25.bin","rb");
+ if (!f) break;
+ romfread(rom, 0x20000, 1, f);
+ fclose(f);
+ biosmask = 0x1ffff;
+ return 1;
+
+ case ROM_BULL_MICRAL_45:
+ f = romfopen("bull_micral_45/even.fil", "rb");
+ ff = romfopen("bull_micral_45/odd.fil", "rb");
+ if (!f || !ff) break;
+ for (c = 0x0000; c < 0x10000; c += 2)
+ {
+ rom[c] = getc(f);
+ rom[c+1] = getc(ff);
+ }
+ fclose(ff);
+ fclose(f);
+ return 1;
+
case ROM_FIC_VA503P:
f = romfopen("fic_va503p/je4333.bin","rb");
if (!f) break;
@@ -908,6 +1100,90 @@ int loadbios()
fclose(f);
biosmask = 0x1ffff;
return 1;
+
+ case ROM_CBM_SL386SX25:
+ f = romfopen("cbm_sl386sx25/f000.rom", "rb");
+ if (!f) break;
+ romfread(rom, 0x10000, 1, f);
+ fclose(f);
+ return 1;
+
+ case ROM_IBMPS1_2133_451:
+ f = romfopen("ibmps1_2133/PS1_2133_52G2974_ROM.bin", "rb");
+ if (!f) break;
+ romfread(rom, 0x20000, 1, f);
+ fclose(f);
+ biosmask = 0x1ffff;
+ return 1;
+
+ case ROM_ECS_386_32:
+ f = romfopen("ecs386_32/386_32_even.bin", "rb");
+ ff = romfopen("ecs386_32/386_32_odd.bin", "rb");
+ if (!f || !ff) break;
+ for (c = 0x0000; c < 0x10000; c += 2)
+ {
+ rom[c] = getc(f);
+ rom[c+1] = getc(ff);
+ }
+ fclose(ff);
+ fclose(f);
+ return 1;
+
+ case ROM_LEDGE_MODELM:
+ f = romfopen("leadingedge_modelm/Leading Edge - Model M - BIOS ROM - Version 4.71.bin","rb");
+ if (!f) break;
+ romfread(rom, 0x4000, 1, f);
+ fclose(f);
+ biosmask = 0x3fff;
+ return 1;
+
+ case ROM_DESKPRO:
+ f = romfopen("deskpro/Compaq - BIOS - Revision J - 106265-002.bin","rb");
+ if (!f) break;
+ romfread(rom, 0x2000, 1, f);
+ fclose(f);
+ biosmask = 0x1fff;
+ return 1;
+
+ case ROM_VS440FX:
+ f = romfopen("vs440fx/1018CS1_.BIO", "rb");
+ if (!f) break;
+ fseek(f, 0x80, SEEK_SET);
+ romfread(rom + 0x10000, 0x10000, 1, f);
+ fclose(f);
+ f = romfopen("vs440fx/1018CS1_.BI1", "rb");
+ if (!f) break;
+ fseek(f, 0x80, SEEK_SET);
+ romfread(rom + 0x00000, 0x10000, 1, f);
+ fclose(f);
+ f = romfopen("vs440fx/1018CS1_.BI2", "rb");
+ if (!f) break;
+ fseek(f, 0x80, SEEK_SET);
+ romfread(rom + 0x30000, 0x10000, 1, f);
+ fclose(f);
+ f = romfopen("vs440fx/1018CS1_.BI3", "rb");
+ if (!f) break;
+ fseek(f, 0x80, SEEK_SET);
+ romfread(rom + 0x20000, 0x0a000, 1, f);
+ fclose(f);
+
+ f = romfopen("vs440fx/1018CS1_.RCV", "rb");
+ if (!f) break;
+ fseek(f, 0x80, SEEK_SET);
+ romfread(rom + 0x2c000, 0x04000, 1, f);
+ fclose(f);
+
+ biosmask = 0x3ffff;
+ return 1;
+
+ case ROM_GA686BX:
+ f = romfopen("ga686bx/6BX.F2a", "rb");
+ if (!f) break;
+ romfread(rom, 0x40000, 1, f);
+ fclose(f);
+
+ biosmask = 0x3ffff;
+ return 1;
}
printf("Failed to load ROM!\n");
if (f) fclose(f);
diff --git a/src/mfm_at.c b/src/mfm_at.c
index 83fee43..9293f18 100644
--- a/src/mfm_at.c
+++ b/src/mfm_at.c
@@ -21,6 +21,14 @@
#define IDE_TIME (TIMER_USEC*10)//(5 * 100 * (1 << TIMER_SHIFT))
+/*Rough estimate - MFM drives spin at 3600 RPM, with 17 sectors per track,
+ meaning (3600/60)*17 = 1020 sectors per second, or 980us per sector.
+
+ This is required for OS/2 on slow 286 systems, as the hard drive formatter
+ will crash with 'internal processing error' if write sector interrupts are too
+ close in time*/
+#define SECTOR_TIME (TIMER_USEC * 980)
+
#define STAT_ERR 0x01
#define STAT_INDEX 0x02
#define STAT_CORRECTED_DATA 0x04
@@ -313,7 +321,7 @@ void mfm_writew(uint16_t port, uint16_t val, void *p)
{
mfm->pos = 0;
mfm->status = STAT_BUSY;
- timer_set_delay_u64(&mfm->callback_timer, 6*IDE_TIME);
+ timer_set_delay_u64(&mfm->callback_timer, SECTOR_TIME);
}
}
@@ -381,8 +389,8 @@ uint16_t mfm_readw(uint16_t port, void *p)
if (mfm->secount)
{
mfm_next_sector(mfm);
- mfm->status = STAT_BUSY;
- timer_set_delay_u64(&mfm->callback_timer, 6*IDE_TIME);
+ mfm->status = STAT_BUSY | STAT_READY | STAT_DSC;
+ timer_set_delay_u64(&mfm->callback_timer, SECTOR_TIME);
}
}
}
diff --git a/src/midi_alsa.c b/src/midi_alsa.c
index f513c23..5b8a2cc 100644
--- a/src/midi_alsa.c
+++ b/src/midi_alsa.c
@@ -124,7 +124,7 @@ static int midi_pos, midi_len;
static uint8_t midi_command[4];
static int midi_lengths[8] = {3, 3, 3, 3, 2, 2, 3, 1};
static int midi_insysex;
-static uint8_t midi_sysex_data[1024+2];
+static uint8_t midi_sysex_data[65536];
void midi_write(uint8_t val)
{
@@ -143,7 +143,7 @@ void midi_write(uint8_t val)
{
midi_sysex_data[midi_pos++] = val;
- if (val == 0xf7 || midi_pos >= 1024+2)
+ if (val == 0xf7 || midi_pos >= 65536)
{
/* pclog("MIDI send sysex %i: ", midi_pos);
for (int i = 0; i < midi_pos; i++)
@@ -157,15 +157,18 @@ void midi_write(uint8_t val)
}
if (midi_len)
- {
- midi_command[midi_pos] = val;
-
- midi_pos++;
-
- if (midi_pos == midi_len)
+ {
+ if (midi_pos < 3)
{
-// pclog("MIDI send %i: %02x %02x %02x %02x\n", midi_len, midi_command[0], midi_command[1], midi_command[2], midi_command[3]);
- snd_rawmidi_write(midiout, midi_command, midi_len);
+ midi_command[midi_pos] = val;
+
+ midi_pos++;
+
+ if (midi_pos == midi_len)
+ {
+// pclog("MIDI send %i: %02x %02x %02x %02x\n", midi_len, midi_command[0], midi_command[1], midi_command[2], midi_command[3]);
+ snd_rawmidi_write(midiout, midi_command, midi_len);
+ }
}
}
}
diff --git a/src/minivhd/CREDITS.md b/src/minivhd/CREDITS.md
new file mode 100644
index 0000000..c494d4e
--- /dev/null
+++ b/src/minivhd/CREDITS.md
@@ -0,0 +1,12 @@
+# Credits
+MiniVHD Copyright (c) 2019 Sherman Perry
+
+MiniVHD was made possible with the help of the following projects
+
+### libxml2
+**Project Home:** http://www.xmlsoft.org/
+**License:** MIT (see src/libxml2_encoding.c for details)
+
+### cwalk
+**Project Home:** https://likle.github.io/cwalk/
+**Licence:** MIT (https://github.com/likle/cwalk/blob/master/LICENSE.md)
diff --git a/src/minivhd/LICENSE b/src/minivhd/LICENSE
new file mode 100644
index 0000000..b5392e6
--- /dev/null
+++ b/src/minivhd/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019-2020 Sherman Perry
+
+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.
\ No newline at end of file
diff --git a/src/minivhd/cwalk.c b/src/minivhd/cwalk.c
new file mode 100644
index 0000000..f0c4842
--- /dev/null
+++ b/src/minivhd/cwalk.c
@@ -0,0 +1,1424 @@
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+#include
+#include
+#include
+#include
+#include
+#include "cwalk.h"
+/**
+ * We try to default to a different path style depending on the operating
+ * system. So this should detect whether we should use windows or unix paths.
+ */
+#if defined(WIN32) || defined(_WIN32) || \
+ defined(__WIN32) && !defined(__CYGWIN__)
+static enum cwk_path_style path_style = CWK_STYLE_WINDOWS;
+#else
+static enum cwk_path_style path_style = CWK_STYLE_UNIX;
+#endif
+
+/**
+ * This is a list of separators used in different styles. Windows can read
+ * multiple separators, but it generally outputs just a backslash. The output
+ * will always use the first character for the output.
+ */
+static const char *separators[] = {[CWK_STYLE_WINDOWS] = "\\/",
+ [CWK_STYLE_UNIX] = "/"};
+
+/**
+ * A joined path represents multiple path strings which are concatenated, but
+ * not (necessarily) stored in contiguous memory. The joined path allows to
+ * iterate over the segments as if it was one piece of path.
+ */
+struct cwk_segment_joined
+{
+ struct cwk_segment segment;
+ const char **paths;
+ size_t path_index;
+};
+
+static size_t cwk_path_output_sized(char *buffer, size_t buffer_size,
+ size_t position, const char *str, size_t length)
+{
+ size_t amount_written;
+
+ // First we determine the amount which we can write to the buffer. There are
+ // three cases. In the first case we have enough to store the whole string in
+ // it. In the second one we can only store a part of it, and in the third we
+ // have no space left.
+ if (buffer_size > position + length) {
+ amount_written = length;
+ } else if (buffer_size > position) {
+ amount_written = buffer_size - position;
+ } else {
+ amount_written = 0;
+ }
+
+ // If we actually want to write out something we will do that here. We will
+ // always append a '\0', this way we are guaranteed to have a valid string at
+ // all times.
+ if (amount_written > 0) {
+ memmove(&buffer[position], str, amount_written);
+ }
+
+ // Return the theoretical length which would have been written when everything
+ // would have fit in the buffer.
+ return length;
+}
+
+static size_t cwk_path_output_current(char *buffer, size_t buffer_size,
+ size_t position)
+{
+ // We output a "current" directory, which is a single character. This
+ // character is currently not style dependant.
+ return cwk_path_output_sized(buffer, buffer_size, position, ".", 1);
+}
+
+static size_t cwk_path_output_back(char *buffer, size_t buffer_size,
+ size_t position)
+{
+ // We output a "back" directory, which ahs two characters. This
+ // character is currently not style dependant.
+ return cwk_path_output_sized(buffer, buffer_size, position, "..", 2);
+}
+
+static size_t cwk_path_output_separator(char *buffer, size_t buffer_size,
+ size_t position)
+{
+ // We output a separator, which is a single character.
+ return cwk_path_output_sized(buffer, buffer_size, position,
+ separators[path_style], 1);
+}
+
+static size_t cwk_path_output_dot(char *buffer, size_t buffer_size,
+ size_t position)
+{
+ // We output a dot, which is a single character. This is used for extensions.
+ return cwk_path_output_sized(buffer, buffer_size, position, ".", 1);
+}
+
+static size_t cwk_path_output(char *buffer, size_t buffer_size, size_t position,
+ const char *str)
+{
+ size_t length;
+
+ // This just does a sized output internally, but first measuring the
+ // null-terminated string.
+ length = strlen(str);
+ return cwk_path_output_sized(buffer, buffer_size, position, str, length);
+}
+
+static void cwk_path_terminate_output(char *buffer, size_t buffer_size,
+ size_t pos)
+{
+ if (buffer_size > 0) {
+ if (pos >= buffer_size) {
+ buffer[buffer_size - 1] = '\0';
+ } else {
+ buffer[pos] = '\0';
+ }
+ }
+}
+
+static bool cwk_path_is_string_equal(const char *first, const char *second,
+ size_t n)
+{
+ // If the path style is UNIX, we will compare case sensitively. This can be
+ // done easily using strncmp.
+ if (path_style == CWK_STYLE_UNIX) {
+ return strncmp(first, second, n) == 0;
+ }
+
+ // However, if this is windows we will have to compare case insensitively.
+ // Since there is no standard method to do that we will have to do it on our
+ // own.
+ while (*first && *second && n > 0) {
+ // We can consider the string to be not equal if the two lowercase
+ // characters are not equal.
+ if (tolower(*first++) != tolower(*second++)) {
+ return false;
+ }
+
+ --n;
+ }
+
+ // We can consider the string to be equal if we either reached n == 0 or both
+ // cursors point to a null character.
+ return n == 0 || (*first == '\0' && *second == '\0');
+}
+
+static const char *cwk_path_find_next_stop(const char *c)
+{
+ // We just move forward until we find a '\0' or a separator, which will be our
+ // next "stop".
+ while (*c != '\0' && !cwk_path_is_separator(c)) {
+ ++c;
+ }
+
+ // Return the pointer of the next stop.
+ return c;
+}
+
+static const char *cwk_path_find_previous_stop(const char *begin, const char *c)
+{
+ // We just move back until we find a separator or reach the beginning of the
+ // path, which will be our previous "stop".
+ while (c > begin && !cwk_path_is_separator(c)) {
+ --c;
+ }
+
+ // Return the pointer to the previous stop. We have to return the first
+ // character after the separator, not on the separator itself.
+ if (cwk_path_is_separator(c)) {
+ return c + 1;
+ } else {
+ return c;
+ }
+}
+
+static bool cwk_path_get_first_segment_without_root(const char *path,
+ const char *segments, struct cwk_segment *segment)
+{
+ // Let's remember the path. We will move the path pointer afterwards, that's
+ // why this has to be done first.
+ segment->path = path;
+ segment->segments = segments;
+
+ // Now let's check whether this is an empty string. An empty string has no
+ // segment it could use.
+ if (*segments == '\0') {
+ return false;
+ }
+
+ // If the string starts with separators, we will jump over those. If there is
+ // only a slash and a '\0' after it, we can't determine the first segment
+ // since there is none.
+ while (cwk_path_is_separator(segments)) {
+ ++segments;
+ if (*segments == '\0') {
+ return false;
+ }
+ }
+
+ // So this is the beginning of our segment.
+ segment->begin = segments;
+
+ // Now let's determine the end of the segment, which we do by moving the path
+ // pointer further until we find a separator.
+ segments = cwk_path_find_next_stop(segments);
+
+ // And finally, calculate the size of the segment by subtracting the position
+ // from the end.
+ segment->size = segments - segment->begin;
+ segment->end = segments;
+
+ // Tell the caller that we found a segment.
+ return true;
+}
+
+static bool cwk_path_get_last_segment_without_root(const char *path,
+ struct cwk_segment *segment)
+{
+ // Now this is fairly similar to the normal algorithm, however, it will assume
+ // that there is no root in the path. So we grab the first segment at this
+ // position, assuming there is no root.
+ if (!cwk_path_get_first_segment_without_root(path, path, segment)) {
+ return false;
+ }
+
+ // Now we find our last segment. The segment struct of the caller
+ // will contain the last segment, since the function we call here will not
+ // change the segment struct when it reaches the end.
+ while (cwk_path_get_next_segment(segment)) {
+ // We just loop until there is no other segment left.
+ }
+
+ return true;
+}
+
+static bool cwk_path_get_first_segment_joined(const char **paths,
+ struct cwk_segment_joined *sj)
+{
+ bool result;
+
+ // Prepare the first segment. We position the joined segment on the first path
+ // and assign the path array to the struct.
+ sj->path_index = 0;
+ sj->paths = paths;
+
+ // We loop through all paths until we find one which has a segment. The result
+ // is stored in a variable, so we can let the caller know whether we found one
+ // or not.
+ result = false;
+ while (paths[sj->path_index] != NULL &&
+ (result = cwk_path_get_first_segment(paths[sj->path_index],
+ &sj->segment)) == false) {
+ ++sj->path_index;
+ }
+
+ return result;
+}
+
+static bool cwk_path_get_next_segment_joined(struct cwk_segment_joined *sj)
+{
+ bool result;
+
+ if (sj->paths[sj->path_index] == NULL) {
+ // We reached already the end of all paths, so there is no other segment
+ // left.
+ return false;
+ } else if (cwk_path_get_next_segment(&sj->segment)) {
+ // There was another segment on the current path, so we are good to
+ // continue.
+ return true;
+ }
+
+ // We try to move to the next path which has a segment available. We must at
+ // least move one further since the current path reached the end.
+ result = false;
+
+ do {
+ ++sj->path_index;
+
+ // And we obviously have to stop this loop if there are no more paths left.
+ if (sj->paths[sj->path_index] == NULL) {
+ break;
+ }
+
+ // Grab the first segment of the next path and determine whether this path
+ // has anything useful in it. There is one more thing we have to consider
+ // here - for the first time we do this we want to skip the root, but
+ // afterwards we will consider that to be part of the segments.
+ result = cwk_path_get_first_segment_without_root(sj->paths[sj->path_index],
+ sj->paths[sj->path_index], &sj->segment);
+
+ } while (!result);
+
+ // Finally, report the result back to the caller.
+ return result;
+}
+
+static bool cwk_path_get_previous_segment_joined(struct cwk_segment_joined *sj)
+{
+ bool result;
+
+ if (*sj->paths == NULL) {
+ // It's possible that there is no initialized segment available in the
+ // struct since there are no paths. In that case we can return false, since
+ // there is no previous segment.
+ return false;
+ } else if (cwk_path_get_previous_segment(&sj->segment)) {
+ // Now we try to get the previous segment from the current path. If we can
+ // do that successfully, we can let the caller know that we found one.
+ return true;
+ }
+
+ result = false;
+
+ do {
+ // We are done once we reached index 0. In that case there are no more
+ // segments left.
+ if (sj->path_index == 0) {
+ break;
+ }
+
+ // There is another path which we have to inspect. So we decrease the path
+ // index.
+ --sj->path_index;
+
+ // If this is the first path we will have to consider that this path might
+ // include a root, otherwise we just treat is as a segment.
+ if (sj->path_index == 0) {
+ result = cwk_path_get_last_segment(sj->paths[sj->path_index],
+ &sj->segment);
+ } else {
+ result = cwk_path_get_last_segment_without_root(sj->paths[sj->path_index],
+ &sj->segment);
+ }
+
+ } while (!result);
+
+ return result;
+}
+
+static bool cwk_path_segment_back_will_be_removed(struct cwk_segment_joined *sj)
+{
+ enum cwk_segment_type type;
+ int counter;
+
+ // We are handling back segments here. We must verify how many back segments
+ // and how many normal segments come before this one to decide whether we keep
+ // or remove it.
+
+ // The counter determines how many normal segments are our current segment,
+ // which will popped off before us. If the counter goes above zero it means
+ // that our segment will be popped as well.
+ counter = 0;
+
+ // We loop over all previous segments until we either reach the beginning,
+ // which means our segment will not be dropped or the counter goes above zero.
+ while (cwk_path_get_previous_segment_joined(sj)) {
+
+ // Now grab the type. The type determines whether we will increase or
+ // decrease the counter. We don't handle a CWK_CURRENT frame here since it
+ // has no influence.
+ type = cwk_path_get_segment_type(&sj->segment);
+ if (type == CWK_NORMAL) {
+ // This is a normal segment. The normal segment will increase the counter
+ // since it neutralizes one back segment. If we go above zero we can
+ // return immediately.
+ ++counter;
+ if (counter > 0) {
+ return true;
+ }
+ } else if (type == CWK_BACK) {
+ // A CWK_BACK segment will reduce the counter by one. We can not remove a
+ // back segment as long we are not above zero since we don't have the
+ // opposite normal segment which we would remove.
+ --counter;
+ }
+ }
+
+ // We never got a count larger than zero, so we will keep this segment alive.
+ return false;
+}
+
+static bool cwk_path_segment_normal_will_be_removed(
+ struct cwk_segment_joined *sj)
+{
+ enum cwk_segment_type type;
+ int counter;
+
+ // The counter determines how many segments are above our current segment,
+ // which will popped off before us. If the counter goes below zero it means
+ // that our segment will be popped as well.
+ counter = 0;
+
+ // We loop over all following segments until we either reach the end, which
+ // means our segment will not be dropped or the counter goes below zero.
+ while (cwk_path_get_next_segment_joined(sj)) {
+
+ // First, grab the type. The type determines whether we will increase or
+ // decrease the counter. We don't handle a CWK_CURRENT frame here since it
+ // has no influence.
+ type = cwk_path_get_segment_type(&sj->segment);
+ if (type == CWK_NORMAL) {
+ // This is a normal segment. The normal segment will increase the counter
+ // since it will be removed by a "../" before us.
+ ++counter;
+ } else if (type == CWK_BACK) {
+ // A CWK_BACK segment will reduce the counter by one. If we are below zero
+ // we can return immediately.
+ --counter;
+ if (counter < 0) {
+ return true;
+ }
+ }
+ }
+
+ // We never got a negative count, so we will keep this segment alive.
+ return false;
+}
+
+static bool
+cwk_path_segment_will_be_removed(const struct cwk_segment_joined *sj,
+ bool absolute)
+{
+ enum cwk_segment_type type;
+ struct cwk_segment_joined sjc;
+
+ // We copy the joined path so we don't need to modify it.
+ sjc = *sj;
+
+ // First we check whether this is a CWK_CURRENT or CWK_BACK segment, since
+ // those will always be dropped.
+ type = cwk_path_get_segment_type(&sj->segment);
+ if (type == CWK_CURRENT) {
+ return true;
+ } else if (type == CWK_BACK && absolute) {
+ return true;
+ } else if (type == CWK_BACK) {
+ return cwk_path_segment_back_will_be_removed(&sjc);
+ } else {
+ return cwk_path_segment_normal_will_be_removed(&sjc);
+ }
+}
+
+static bool
+cwk_path_segment_joined_skip_invisible(struct cwk_segment_joined *sj,
+ bool absolute)
+{
+ while (cwk_path_segment_will_be_removed(sj, absolute)) {
+ if (!cwk_path_get_next_segment_joined(sj)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void cwk_path_get_root_windows(const char *path, size_t *length)
+{
+ const char *c;
+ bool is_device_path;
+
+ // A device path is a path which starts with "\\." or "\\?". A device path can
+ // be a UNC path as well, in which case it will take up one more segment.
+ is_device_path = false;
+
+ // We can not determine the root if this is an empty string. So we set the
+ // root to NULL and the length to zero and cancel the whole thing.
+ c = path;
+ *length = 0;
+ if (!*c) {
+ return;
+ }
+
+ // Now we have to verify whether this is a windows network path (UNC), which
+ // we will consider our root.
+ if (cwk_path_is_separator(c)) {
+ ++c;
+
+ // Check whether the path starts with a single back slash, which means this
+ // is not a network path - just a normal path starting with a backslash.
+ if (!cwk_path_is_separator(c)) {
+ // Okay, this is not a network path but we still use the backslash as a
+ // root.
+ ++(*length);
+ return;
+ }
+
+ // Yes, this is a network or device path. Skip the previous separator. Now
+ // we need to determine whether this is a device path. We might advance one
+ // character here if the server name starts with a '?' or a '.', but that's
+ // fine since we will search for a separator afterwards anyway.
+ ++c;
+ is_device_path = (*c == '?' || *c == '.') && cwk_path_is_separator(++c);
+ if (is_device_path) {
+ // That's a device path, and the root must be either "\\.\" or "\\?\"
+ // which is 4 characters long. (at least that's how Windows
+ // GetFullPathName behaves.)
+ *length = 4;
+ return;
+ }
+
+ // We will grab anything up to the next stop. The next top might be a '\0'
+ // or another separator. That will be the server name.
+ c = cwk_path_find_next_stop(c);
+
+ // If this is a separator and not the end of a string we wil have to include
+ // it. However, if this is a '\0' we must not skip it.
+ while (cwk_path_is_separator(c)) {
+ ++c;
+ }
+
+ // We are now skipping the shared folder name, which will end after the
+ // next stop.
+ c = cwk_path_find_next_stop(c);
+
+ // Then there might be a separator at the end. We will include that as well,
+ // it will mark the path as absolute.
+ if (cwk_path_is_separator(c)) {
+ ++c;
+ }
+
+ // Finally, calculate the size of the root.
+ *length = c - path;
+ return;
+ }
+
+ // Move to the next and check whether this is a colon.
+ if (*++c == ':') {
+ *length = 2;
+
+ // Now check whether this is a backslash (or slash). If it is not, we could
+ // assume that the next character is a '\0' if it is a valid path. However,
+ // we will not assume that - since ':' is not valid in a path it must be a
+ // mistake by the caller than. We will try to understand it anyway.
+ if (cwk_path_is_separator(++c)) {
+ *length = 3;
+ }
+ }
+}
+
+static void cwk_path_get_root_unix(const char *path, size_t *length)
+{
+ // The slash of the unix path represents the root. There is no root if there
+ // is no slash.
+ if (cwk_path_is_separator(path)) {
+ *length = 1;
+ } else {
+ *length = 0;
+ }
+}
+
+static bool cwk_path_is_root_absolute(const char *path, size_t length)
+{
+ // This is definitely not absolute if there is no root.
+ if (length == 0) {
+ return false;
+ }
+
+ // If there is a separator at the end of the root, we can safely consider this
+ // to be an absolute path.
+ return cwk_path_is_separator(&path[length - 1]);
+}
+
+static size_t cwk_path_join_and_normalize_multiple(const char **paths,
+ char *buffer, size_t buffer_size)
+{
+ size_t pos;
+ bool absolute, has_segment_output;
+ struct cwk_segment_joined sj;
+
+ // We initialize the position after the root, which should get us started.
+ cwk_path_get_root(paths[0], &pos);
+
+ // Determine whether the path is absolute or not. We need that to determine
+ // later on whether we can remove superfluous "../" or not.
+ absolute = cwk_path_is_root_absolute(paths[0], pos);
+
+ // First copy the root to the output. We will not modify the root.
+ cwk_path_output_sized(buffer, buffer_size, 0, paths[0], pos);
+
+ // So we just grab the first segment. If there is no segment we will always
+ // output a "/", since we currently only support absolute paths here.
+ if (!cwk_path_get_first_segment_joined(paths, &sj)) {
+ goto done;
+ }
+
+ // Let's assume that we don't have any segment output for now. We will toggle
+ // this flag once there is some output.
+ has_segment_output = false;
+
+ do {
+ // Check whether we have to drop this segment because of resolving a
+ // relative path or because it is a CWK_CURRENT segment.
+ if (cwk_path_segment_will_be_removed(&sj, absolute)) {
+ continue;
+ }
+
+ // Remember that we have segment output, so we can handle the trailing slash
+ // later on. This is necessary since we might have segments but they are all
+ // removed.
+ has_segment_output = true;
+
+ // Write out the segment but keep in mind that we need to follow the
+ // buffer size limitations. That's why we use the path output functions
+ // here.
+ pos += cwk_path_output_sized(buffer, buffer_size, pos, sj.segment.begin,
+ sj.segment.size);
+ pos += cwk_path_output_separator(buffer, buffer_size, pos);
+ } while (cwk_path_get_next_segment_joined(&sj));
+
+ // Remove the trailing slash, but only if we have segment output. We don't
+ // want to remove anything from the root.
+ if (has_segment_output) {
+ --pos;
+ } else if (pos == 0) {
+ // This may happen if the path is absolute and all segments have been
+ // removed. We can not have an empty output - and empty output means we stay
+ // in the current directory. So we will output a ".".
+ assert(absolute == false);
+ pos += cwk_path_output_current(buffer, buffer_size, pos);
+ }
+
+ // We must append a '\0' in any case, unless the buffer size is zero. If the
+ // buffer size is zero, which means we can not.
+done:
+ cwk_path_terminate_output(buffer, buffer_size, pos);
+
+ // And finally let our caller know about the total size of the normalized
+ // path.
+ return pos;
+}
+
+size_t cwk_path_get_absolute(const char *base, const char *path, char *buffer,
+ size_t buffer_size)
+{
+ size_t i;
+ const char *paths[4];
+
+ // The basename should be an absolute path if the caller is using the API
+ // correctly. However, he might not and in that case we will append a fake
+ // root at the beginning.
+ if (cwk_path_is_absolute(base)) {
+ i = 0;
+ } else {
+ paths[0] = "/";
+ i = 1;
+ }
+
+ if (cwk_path_is_absolute(path)) {
+ // If the submitted path is not relative the base path becomes irrelevant.
+ // We will only normalize the submitted path instead.
+ paths[i++] = path;
+ paths[i] = NULL;
+ } else {
+ // Otherwise we append the relative path to the base path and normalize it.
+ // The result will be a new absolute path.
+ paths[i++] = base;
+ paths[i++] = path;
+ paths[i] = NULL;
+ }
+
+ // Finally join everything together and normalize it.
+ return cwk_path_join_and_normalize_multiple(paths, buffer, buffer_size);
+}
+
+static void cwk_path_skip_segments_until_diverge(struct cwk_segment_joined *bsj,
+ struct cwk_segment_joined *osj, bool absolute, bool *base_available,
+ bool *other_available)
+{
+ // Now looping over all segments until they start to diverge. A path may
+ // diverge if two segments are not equal or if one path reaches the end.
+ do {
+
+ // Check whether there is anything available after we skip everything which
+ // is invisible. We do that for both paths, since we want to let the caller
+ // know which path has some trailing segments after they diverge.
+ *base_available = cwk_path_segment_joined_skip_invisible(bsj, absolute);
+ *other_available = cwk_path_segment_joined_skip_invisible(osj, absolute);
+
+ // We are done if one or both of those paths reached the end. They either
+ // diverge or both reached the end - but in both cases we can not continue
+ // here.
+ if (!*base_available || !*other_available) {
+ break;
+ }
+
+ // Compare the content of both segments. We are done if they are not equal,
+ // since they diverge.
+ if (!cwk_path_is_string_equal(bsj->segment.begin, osj->segment.begin,
+ bsj->segment.size)) {
+ break;
+ }
+
+ // We keep going until one of those segments reached the end. The next
+ // segment might be invisible, but we will check for that in the beginning
+ // of the loop once again.
+ *base_available = cwk_path_get_next_segment_joined(bsj);
+ *other_available = cwk_path_get_next_segment_joined(osj);
+ } while (*base_available && *other_available);
+}
+
+size_t cwk_path_get_relative(const char *base_directory, const char *path,
+ char *buffer, size_t buffer_size)
+{
+ size_t pos, base_root_length, path_root_length;
+ bool absolute, base_available, other_available, has_output;
+ const char *base_paths[2], *other_paths[2];
+ struct cwk_segment_joined bsj, osj;
+
+ pos = 0;
+
+ // First we compare the roots of those two paths. If the roots are not equal
+ // we can't continue, since there is no way to get a relative path from
+ // different roots.
+ cwk_path_get_root(base_directory, &base_root_length);
+ cwk_path_get_root(path, &path_root_length);
+ if (!cwk_path_is_string_equal(base_directory, path, base_root_length)) {
+ return pos;
+ }
+
+ // Verify whether this is an absolute path. We need to know that since we can
+ // remove all back-segments if it is.
+ absolute = cwk_path_is_root_absolute(base_directory, base_root_length);
+
+ // Initialize our joined segments. This will allow us to use the internal
+ // functions to skip until diverge and invisible. We only have one path in
+ // them though.
+ base_paths[0] = base_directory;
+ base_paths[1] = NULL;
+ other_paths[0] = path;
+ other_paths[1] = NULL;
+ cwk_path_get_first_segment_joined(base_paths, &bsj);
+ cwk_path_get_first_segment_joined(other_paths, &osj);
+
+ // Okay, now we skip until the segments diverge. We don't have anything to do
+ // with the segments which are equal.
+ cwk_path_skip_segments_until_diverge(&bsj, &osj, absolute, &base_available,
+ &other_available);
+
+ // Assume there is no output until we have got some. We will need this
+ // information later on to remove trailing slashes or alternatively output a
+ // current-segment.
+ has_output = false;
+
+ // So if we still have some segments left in the base path we will now output
+ // a back segment for all of them.
+ if (base_available) {
+ do {
+ // Skip any invisible segment. We don't care about those and we don't need
+ // to navigate back because of them.
+ if (!cwk_path_segment_joined_skip_invisible(&bsj, absolute)) {
+ break;
+ }
+
+ // Toggle the flag if we have output. We need to remember that, since we
+ // want to remove the trailing slash.
+ has_output = true;
+
+ // Output the back segment and a separator. No need to worry about the
+ // superfluous segment since it will be removed later on.
+ pos += cwk_path_output_back(buffer, buffer_size, pos);
+ pos += cwk_path_output_separator(buffer, buffer_size, pos);
+ } while (cwk_path_get_next_segment_joined(&bsj));
+ }
+
+ // And if we have some segments available of the target path we will output
+ // all of those.
+ if (other_available) {
+ do {
+ // Again, skip any invisible segments since we don't need to navigate into
+ // them.
+ if (!cwk_path_segment_joined_skip_invisible(&osj, absolute)) {
+ break;
+ }
+
+ // Toggle the flag if we have output. We need to remember that, since we
+ // want to remove the trailing slash.
+ has_output = true;
+
+ // Output the current segment and a separator. No need to worry about the
+ // superfluous segment since it will be removed later on.
+ pos += cwk_path_output_sized(buffer, buffer_size, pos, osj.segment.begin,
+ osj.segment.size);
+ pos += cwk_path_output_separator(buffer, buffer_size, pos);
+ } while (cwk_path_get_next_segment_joined(&osj));
+ }
+
+ // If we have some output by now we will have to remove the trailing slash. We
+ // simply do that by moving back one character. The terminate output function
+ // will then place the '\0' on this position. Otherwise, if there is no
+ // output, we will have to output a "current directory", since the target path
+ // points to the base path.
+ if (has_output) {
+ --pos;
+ } else {
+ pos += cwk_path_output_current(buffer, buffer_size, pos);
+ }
+
+ // Finally, we can terminate the output - which means we place a '\0' at the
+ // current position or at the end of the buffer.
+ cwk_path_terminate_output(buffer, buffer_size, pos);
+
+ return pos;
+}
+
+size_t cwk_path_join(const char *path_a, const char *path_b, char *buffer,
+ size_t buffer_size)
+{
+ const char *paths[3];
+
+ // This is simple. We will just create an array with the two paths which we
+ // wish to join.
+ paths[0] = path_a;
+ paths[1] = path_b;
+ paths[2] = NULL;
+
+ // And then call the join and normalize function which will do the hard work
+ // for us.
+ return cwk_path_join_and_normalize_multiple(paths, buffer, buffer_size);
+}
+
+size_t cwk_path_join_multiple(const char **paths, char *buffer,
+ size_t buffer_size)
+{
+ // We can just call the internal join and normalize function for this one,
+ // since it will handle everything.
+ return cwk_path_join_and_normalize_multiple(paths, buffer, buffer_size);
+}
+
+void cwk_path_get_root(const char *path, size_t *length)
+{
+ // We use a different implementation here based on the configuration of the
+ // library.
+ if (path_style == CWK_STYLE_WINDOWS) {
+ cwk_path_get_root_windows(path, length);
+ } else {
+ cwk_path_get_root_unix(path, length);
+ }
+}
+
+size_t cwk_path_change_root(const char *path, const char *new_root,
+ char *buffer, size_t buffer_size)
+{
+ const char *tail;
+ size_t root_length, path_length, tail_length, new_root_length, new_path_size;
+
+ // First we need to determine the actual size of the root which we will
+ // change.
+ cwk_path_get_root(path, &root_length);
+
+ // Now we determine the sizes of the new root and the path. We need that to
+ // determine the size of the part after the root (the tail).
+ new_root_length = strlen(new_root);
+ path_length = strlen(path);
+
+ // Okay, now we calculate the position of the tail and the length of it.
+ tail = path + root_length;
+ tail_length = path_length - root_length;
+
+ // We first output the tail and then the new root, that's because the source
+ // path and the buffer may be overlapping. This way the root will not
+ // overwrite the tail.
+ cwk_path_output_sized(buffer, buffer_size, new_root_length, tail,
+ tail_length);
+ cwk_path_output_sized(buffer, buffer_size, 0, new_root, new_root_length);
+
+ // Finally we calculate the size o the new path and terminate the output with
+ // a '\0'.
+ new_path_size = tail_length + new_root_length;
+ cwk_path_terminate_output(buffer, buffer_size, new_path_size);
+
+ return new_path_size;
+}
+
+bool cwk_path_is_absolute(const char *path)
+{
+ size_t length;
+
+ // We grab the root of the path. This root does not include the first
+ // separator of a path.
+ cwk_path_get_root(path, &length);
+
+ // Now we can determine whether the root is absolute or not.
+ return cwk_path_is_root_absolute(path, length);
+}
+
+bool cwk_path_is_relative(const char *path)
+{
+ // The path is relative if it is not absolute.
+ return !cwk_path_is_absolute(path);
+}
+
+void cwk_path_get_basename(const char *path, const char **basename,
+ size_t *length)
+{
+ struct cwk_segment segment;
+
+ // We get the last segment of the path. The last segment will contain the
+ // basename if there is any. If there are no segments we will set the basename
+ // to NULL and the length to 0.
+ if (!cwk_path_get_last_segment(path, &segment)) {
+ *basename = NULL;
+ *length = 0;
+ return;
+ }
+
+ // Now we can just output the segment contents, since that's our basename.
+ // There might be trailing separators after the basename, but the size does
+ // not include those.
+ *basename = segment.begin;
+ *length = segment.size;
+}
+
+size_t cwk_path_change_basename(const char *path, const char *new_basename,
+ char *buffer, size_t buffer_size)
+{
+ struct cwk_segment segment;
+ size_t pos, root_size, new_basename_size;
+
+ // First we try to get the last segment. We may only have a root without any
+ // segments, in which case we will create one.
+ if (!cwk_path_get_last_segment(path, &segment)) {
+
+ // So there is no segment in this path. First we grab the root and output
+ // that. We are not going to modify the root in any way.
+ cwk_path_get_root(path, &root_size);
+ pos = cwk_path_output_sized(buffer, buffer_size, 0, path, root_size);
+
+ // We have to trim the separators from the beginning of the new basename.
+ // This is quite easy to do.
+ while (cwk_path_is_separator(new_basename)) {
+ ++new_basename;
+ }
+
+ // Now we measure the length of the new basename, this is a two step
+ // process. First we find the '\0' character at the end of the string.
+ new_basename_size = 0;
+ while (new_basename[new_basename_size]) {
+ ++new_basename_size;
+ }
+
+ // And then we trim the separators at the end of the basename until we reach
+ // the first valid character.
+ while (new_basename_size > 0 &&
+ cwk_path_is_separator(&new_basename[new_basename_size - 1])) {
+ --new_basename_size;
+ }
+
+ // Now we will output the new basename after the root.
+ pos += cwk_path_output_sized(buffer, buffer_size, pos, new_basename,
+ new_basename_size);
+
+ // And finally terminate the output and return the total size of the path.
+ cwk_path_terminate_output(buffer, buffer_size, pos);
+ return pos;
+ }
+
+ // If there is a last segment we can just forward this call, which is fairly
+ // easy.
+ return cwk_path_change_segment(&segment, new_basename, buffer, buffer_size);
+}
+
+void cwk_path_get_dirname(const char *path, size_t *length)
+{
+ struct cwk_segment segment;
+
+ // We get the last segment of the path. The last segment will contain the
+ // basename if there is any. If there are no segments we will set the length
+ // to 0.
+ if (!cwk_path_get_last_segment(path, &segment)) {
+ *length = 0;
+ return;
+ }
+
+ // We can now return the length from the beginning of the string up to the
+ // beginning of the last segment.
+ *length = segment.begin - path;
+}
+
+bool cwk_path_get_extension(const char *path, const char **extension,
+ size_t *length)
+{
+ struct cwk_segment segment;
+ const char *c;
+
+ // We get the last segment of the path. The last segment will contain the
+ // extension if there is any.
+ if (!cwk_path_get_last_segment(path, &segment)) {
+ return false;
+ }
+
+ // Now we search for a dot within the segment. If there is a dot, we consider
+ // the rest of the segment the extension. We do this from the end towards the
+ // beginning, since we want to find the last dot.
+ for (c = segment.end; c >= segment.begin; --c) {
+ if (*c == '.') {
+ // Okay, we found an extension. We can stop looking now.
+ *extension = c;
+ *length = segment.end - c;
+ return true;
+ }
+ }
+
+ // We couldn't find any extension.
+ return false;
+}
+
+bool cwk_path_has_extension(const char *path)
+{
+ const char *extension;
+ size_t length;
+
+ // We just wrap the get_extension call which will then do the work for us.
+ return cwk_path_get_extension(path, &extension, &length);
+}
+
+size_t cwk_path_change_extension(const char *path, const char *new_extension,
+ char *buffer, size_t buffer_size)
+{
+ struct cwk_segment segment;
+ const char *c, *old_extension;
+ size_t pos, root_size, trail_size, new_extension_size;
+
+ // First we try to get the last segment. We may only have a root without any
+ // segments, in which case we will create one.
+ if (!cwk_path_get_last_segment(path, &segment)) {
+
+ // So there is no segment in this path. First we grab the root and output
+ // that. We are not going to modify the root in any way. If there is no
+ // root, this will end up with a root size 0, and nothing will be written.
+ cwk_path_get_root(path, &root_size);
+ pos = cwk_path_output_sized(buffer, buffer_size, 0, path, root_size);
+
+ // Add a dot if the submitted value doesn't have any.
+ if (*new_extension != '.') {
+ pos += cwk_path_output_dot(buffer, buffer_size, pos);
+ }
+
+ // And finally terminate the output and return the total size of the path.
+ pos += cwk_path_output(buffer, buffer_size, pos, new_extension);
+ cwk_path_terminate_output(buffer, buffer_size, pos);
+ return pos;
+ }
+
+ // Now we seek the old extension in the last segment, which we will replace
+ // with the new one. If there is no old extension, it will point to the end of
+ // the segment.
+ old_extension = segment.end;
+ for (c = segment.begin; c < segment.end; ++c) {
+ if (*c == '.') {
+ old_extension = c;
+ }
+ }
+
+ pos = cwk_path_output_sized(buffer, buffer_size, 0, segment.path,
+ old_extension - segment.path);
+
+ // If the new extension starts with a dot, we will skip that dot. We always
+ // output exactly one dot before the extension. If the extension contains
+ // multiple dots, we will output those as part of the extension.
+ if (*new_extension == '.') {
+ ++new_extension;
+ }
+
+ // We calculate the size of the new extension, including the dot, in order to
+ // output the trail - which is any part of the path coming after the
+ // extension. We must output this first, since the buffer may overlap with the
+ // submitted path - and it would be overridden by longer extensions.
+ new_extension_size = strlen(new_extension) + 1;
+ trail_size = cwk_path_output(buffer, buffer_size, pos + new_extension_size,
+ segment.end);
+
+ // Finally we output the dot and the new extension. The new extension itself
+ // doesn't contain the dot anymore, so we must output that first.
+ pos += cwk_path_output_dot(buffer, buffer_size, pos);
+ pos += cwk_path_output(buffer, buffer_size, pos, new_extension);
+
+ // Now we terminate the output with a null-terminating character, but before
+ // we do that we must add the size of the trail to the position which we
+ // output before.
+ pos += trail_size;
+ cwk_path_terminate_output(buffer, buffer_size, pos);
+
+ // And the position is our output size now.
+ return pos;
+}
+
+size_t cwk_path_normalize(const char *path, char *buffer, size_t buffer_size)
+{
+ const char *paths[2];
+
+ // Now we initialize the paths which we will normalize. Since this function
+ // only supports submitting a single path, we will only add that one.
+ paths[0] = path;
+ paths[1] = NULL;
+
+ return cwk_path_join_and_normalize_multiple(paths, buffer, buffer_size);
+}
+
+size_t cwk_path_get_intersection(const char *path_base, const char *path_other)
+{
+ bool absolute;
+ size_t base_root_length, other_root_length;
+ const char *end;
+ const char *paths_base[2], *paths_other[2];
+ struct cwk_segment_joined base, other;
+
+ // We first compare the two roots. We just return zero if they are not equal.
+ // This will also happen to return zero if the paths are mixed relative and
+ // absolute.
+ cwk_path_get_root(path_base, &base_root_length);
+ cwk_path_get_root(path_other, &other_root_length);
+ if (!cwk_path_is_string_equal(path_base, path_other, base_root_length)) {
+ return 0;
+ }
+
+ // Configure our paths. We just have a single path in here for now.
+ paths_base[0] = path_base;
+ paths_base[1] = NULL;
+ paths_other[0] = path_other;
+ paths_other[1] = NULL;
+
+ // So we get the first segment of both paths. If one of those paths don't have
+ // any segment, we will return 0.
+ if (!cwk_path_get_first_segment_joined(paths_base, &base) ||
+ !cwk_path_get_first_segment_joined(paths_other, &other)) {
+ return base_root_length;
+ }
+
+ // We now determine whether the path is absolute or not. This is required
+ // because if will ignore removed segments, and this behaves differently if
+ // the path is absolute. However, we only need to check the base path because
+ // we are guaranteed that both paths are either relative or absolute.
+ absolute = cwk_path_is_root_absolute(path_base, base_root_length);
+
+ // We must keep track of the end of the previous segment. Initially, this is
+ // set to the beginning of the path. This means that 0 is returned if the
+ // first segment is not equal.
+ end = path_base + base_root_length;
+
+ // Now we loop over both segments until one of them reaches the end or their
+ // contents are not equal.
+ do {
+ // We skip all segments which will be removed in each path, since we want to
+ // know about the true path.
+ if (!cwk_path_segment_joined_skip_invisible(&base, absolute) ||
+ !cwk_path_segment_joined_skip_invisible(&other, absolute)) {
+ break;
+ }
+
+ if (!cwk_path_is_string_equal(base.segment.begin, other.segment.begin,
+ base.segment.size)) {
+ // So the content of those two segments are not equal. We will return the
+ // size up to the beginning.
+ return end - path_base;
+ }
+
+ // Remember the end of the previous segment before we go to the next one.
+ end = base.segment.end;
+ } while (cwk_path_get_next_segment_joined(&base) &&
+ cwk_path_get_next_segment_joined(&other));
+
+ // Now we calculate the length up to the last point where our paths pointed to
+ // the same place.
+ return end - path_base;
+}
+
+bool cwk_path_get_first_segment(const char *path, struct cwk_segment *segment)
+{
+ size_t length;
+ const char *segments;
+
+ // We skip the root since that's not part of the first segment. The root is
+ // treated as a separate entity.
+ cwk_path_get_root(path, &length);
+ segments = path + length;
+
+ // Now, after we skipped the root we can continue and find the actual segment
+ // content.
+ return cwk_path_get_first_segment_without_root(path, segments, segment);
+}
+
+bool cwk_path_get_last_segment(const char *path, struct cwk_segment *segment)
+{
+ // We first grab the first segment. This might be our last segment as well,
+ // but we don't know yet. There is no last segment if there is no first
+ // segment, so we return false in that case.
+ if (!cwk_path_get_first_segment(path, segment)) {
+ return false;
+ }
+
+ // Now we find our last segment. The segment struct of the caller
+ // will contain the last segment, since the function we call here will not
+ // change the segment struct when it reaches the end.
+ while (cwk_path_get_next_segment(segment)) {
+ // We just loop until there is no other segment left.
+ }
+
+ return true;
+}
+
+bool cwk_path_get_next_segment(struct cwk_segment *segment)
+{
+ const char *c;
+
+ // First we jump to the end of the previous segment. The first character must
+ // be either a '\0' or a separator.
+ c = segment->begin + segment->size;
+ if (*c == '\0') {
+ return false;
+ }
+
+ // Now we skip all separator until we reach something else. We are not yet
+ // guaranteed to have a segment, since the string could just end afterwards.
+ assert(cwk_path_is_separator(c));
+ do {
+ ++c;
+ } while (cwk_path_is_separator(c));
+
+ // If the string ends here, we can safely assume that there is no other
+ // segment after this one.
+ if (*c == '\0') {
+ return false;
+ }
+
+ // Now we are safe to assume there is a segment. We store the beginning of
+ // this segment in the segment struct of the caller.
+ segment->begin = c;
+
+ // And now determine the size of this segment, and store it in the struct of
+ // the caller as well.
+ c = cwk_path_find_next_stop(c);
+ segment->end = c;
+ segment->size = c - segment->begin;
+
+ // Tell the caller that we found a segment.
+ return true;
+}
+
+bool cwk_path_get_previous_segment(struct cwk_segment *segment)
+{
+ const char *c;
+
+ // The current position might point to the first character of the path, which
+ // means there are no previous segments available.
+ c = segment->begin;
+ if (c <= segment->segments) {
+ return false;
+ }
+
+ // We move towards the beginning of the path until we either reached the
+ // beginning or the character is no separator anymore.
+ do {
+ --c;
+ if (c <= segment->segments) {
+ // So we reached the beginning here and there is no segment. So we return
+ // false and don't change the segment structure submitted by the caller.
+ return false;
+ }
+ } while (cwk_path_is_separator(c));
+
+ // We are guaranteed now that there is another segment, since we moved before
+ // the previous separator and did not reach the segment path beginning.
+ segment->end = c + 1;
+ segment->begin = cwk_path_find_previous_stop(segment->segments, c);
+ segment->size = segment->end - segment->begin;
+
+ return true;
+}
+
+enum cwk_segment_type cwk_path_get_segment_type(
+ const struct cwk_segment *segment)
+{
+ // We just make a string comparison with the segment contents and return the
+ // appropriate type.
+ if (strncmp(segment->begin, ".", segment->size) == 0) {
+ return CWK_CURRENT;
+ } else if (strncmp(segment->begin, "..", segment->size) == 0) {
+ return CWK_BACK;
+ }
+
+ return CWK_NORMAL;
+}
+
+bool cwk_path_is_separator(const char *str)
+{
+ const char *c;
+
+ // We loop over all characters in the read symbols.
+ c = separators[path_style];
+ while (*c) {
+ if (*c == *str) {
+ return true;
+ }
+
+ ++c;
+ }
+
+ return false;
+}
+
+size_t cwk_path_change_segment(struct cwk_segment *segment, const char *value,
+ char *buffer, size_t buffer_size)
+{
+ size_t pos, value_size, tail_size;
+
+ // First we have to output the head, which is the whole string up to the
+ // beginning of the segment. This part of the path will just stay the same.
+ pos = cwk_path_output_sized(buffer, buffer_size, 0, segment->path,
+ segment->begin - segment->path);
+
+ // In order to trip the submitted value, we will skip any separator at the
+ // beginning of it and behave as if it was never there.
+ while (cwk_path_is_separator(value)) {
+ ++value;
+ }
+
+ // Now we determine the length of the value. In order to do that we first
+ // locate the '\0'.
+ value_size = 0;
+ while (value[value_size]) {
+ ++value_size;
+ }
+
+ // Since we trim separators at the beginning and in the end of the value we
+ // have to subtract from the size until there are either no more characters
+ // left or the last character is no separator.
+ while (value_size > 0 && cwk_path_is_separator(&value[value_size - 1])) {
+ --value_size;
+ }
+
+ // We also have to determine the tail size, which is the part of the string
+ // following the current segment. This part will not change.
+ tail_size = strlen(segment->end);
+
+ // Now we output the tail. We have to do that, because if the buffer and the
+ // source are overlapping we would override the tail if the value is
+ // increasing in length.
+ cwk_path_output_sized(buffer, buffer_size, pos + value_size, segment->end,
+ tail_size);
+
+ // Finally we can output the value in the middle of the head and the tail,
+ // where we have enough space to fit the whole trimmed value.
+ pos += cwk_path_output_sized(buffer, buffer_size, pos, value, value_size);
+
+ // Now we add the tail size to the current position and terminate the output -
+ // basically, ensure that there is a '\0' at the end of the buffer.
+ pos += tail_size;
+ cwk_path_terminate_output(buffer, buffer_size, pos);
+
+ // And now tell the caller how long the whole path would be.
+ return pos;
+}
+
+enum cwk_path_style cwk_path_guess_style(const char *path)
+{
+ const char *c;
+ size_t root_length;
+ struct cwk_segment segment;
+
+ // First we determine the root. Only windows roots can be longer than a single
+ // slash, so if we can determine that it starts with something like "C:", we
+ // know that this is a windows path.
+ cwk_path_get_root_windows(path, &root_length);
+ if (root_length > 1) {
+ return CWK_STYLE_WINDOWS;
+ }
+
+ // Next we check for slashes. Windows uses backslashes, while unix uses
+ // forward slashes. Windows actually supports both, but our best guess is to
+ // assume windows with backslashes and unix with forward slashes.
+ for (c = path; *c; ++c) {
+ if (*c == *separators[CWK_STYLE_UNIX]) {
+ return CWK_STYLE_UNIX;
+ } else if (*c == *separators[CWK_STYLE_WINDOWS]) {
+ return CWK_STYLE_WINDOWS;
+ }
+ }
+
+ // This path does not have any slashes. We grab the last segment (which
+ // actually must be the first one), and determine whether the segment starts
+ // with a dot. A dot is a hidden folder or file in the UNIX world, in that
+ // case we assume the path to have UNIX style.
+ if (!cwk_path_get_last_segment(path, &segment)) {
+ // We couldn't find any segments, so we default to a UNIX path style since
+ // there is no way to make any assumptions.
+ return CWK_STYLE_UNIX;
+ }
+
+ if (*segment.begin == '.') {
+ return CWK_STYLE_UNIX;
+ }
+
+ // And finally we check whether the last segment contains a dot. If it
+ // contains a dot, that might be an extension. Windows is more likely to have
+ // file names with extensions, so our guess would be windows.
+ for (c = segment.begin; *c; ++c) {
+ if (*c == '.') {
+ return CWK_STYLE_WINDOWS;
+ }
+ }
+
+ // All our checks failed, so we will return a default value which is currently
+ // UNIX.
+ return CWK_STYLE_UNIX;
+}
+
+void cwk_path_set_style(enum cwk_path_style style)
+{
+ // We can just set the global path style variable and then the behaviour for
+ // all functions will change accordingly.
+ assert(style == CWK_STYLE_UNIX || style == CWK_STYLE_WINDOWS);
+ path_style = style;
+}
+
+enum cwk_path_style cwk_path_get_style(void)
+{
+ // Simply return the path style which we store in a global variable.
+ return path_style;
+}
diff --git a/src/minivhd/cwalk.h b/src/minivhd/cwalk.h
new file mode 100644
index 0000000..baa5d43
--- /dev/null
+++ b/src/minivhd/cwalk.h
@@ -0,0 +1,457 @@
+#pragma once
+
+#ifndef CWK_LIBRARY_H
+#define CWK_LIBRARY_H
+
+#include
+#include
+
+/**
+ * A segment represents a single component of a path. For instance, on linux a
+ * path might look like this "/var/log/", which consists of two segments "var"
+ * and "log".
+ */
+struct cwk_segment
+{
+ const char *path;
+ const char *segments;
+ const char *begin;
+ const char *end;
+ size_t size;
+};
+
+/**
+ * The segment type can be used to identify whether a segment is a special
+ * segment or not.
+ *
+ * CWK_NORMAL - normal folder or file segment
+ * CWK_CURRENT - "./" current folder segment
+ * CWK_BACK - "../" relative back navigation segment
+ */
+enum cwk_segment_type
+{
+ CWK_NORMAL,
+ CWK_CURRENT,
+ CWK_BACK
+};
+
+/**
+ * @brief Determines the style which is used for the path parsing and
+ * generation.
+ */
+enum cwk_path_style
+{
+ CWK_STYLE_WINDOWS,
+ CWK_STYLE_UNIX
+};
+
+/**
+ * @brief Generates an absolute path based on a base.
+ *
+ * This function generates an absolute path based on a base path and another
+ * path. It is guaranteed to return an absolute path. If the second submitted
+ * path is absolute, it will override the base path. The result will be written
+ * to a buffer, which might be truncated if the buffer is not large enough to
+ * hold the full path. However, the truncated result will always be
+ * null-terminated. The returned value is the amount of characters which the
+ * resulting path would take if it was not truncated (excluding the
+ * null-terminating character).
+ *
+ * @param base The base path on which the relative path will be applied.
+ * @param path The relative path which will be applied on the base path.
+ * @param buffer The buffer where the result will be written to.
+ * @param buffer_size The size of the result buffer.
+ * @return Returns the total amount of characters of the new absolute path.
+ */
+size_t cwk_path_get_absolute(const char *base, const char *path, char *buffer,
+ size_t buffer_size);
+
+/**
+ * @brief Generates a relative path based on a base.
+ *
+ * This function generates a relative path based on a base path and another
+ * path. It determines how to get to the submitted path, starting from the base
+ * directory. The result will be written to a buffer, which might be truncated
+ * if the buffer is not large enough to hold the full path. However, the
+ * truncated result will always be null-terminated. The returned value is the
+ * amount of characters which the resulting path would take if it was not
+ * truncated (excluding the null-terminating character).
+ *
+ * @param base_directory The base path from which the relative path will start.
+ * @param path The target path where the relative path will point to.
+ * @param buffer The buffer where the result will be written to.
+ * @param buffer_size The size of the result buffer.
+ * @return Returns the total amount of characters of the full path.
+ */
+size_t cwk_path_get_relative(const char *base_directory, const char *path,
+ char *buffer, size_t buffer_size);
+
+/**
+ * @brief Joins two paths together.
+ *
+ * This function generates a new path by combining the two submitted paths. It
+ * will remove double separators, and unlike cwk_path_get_absolute it permits
+ * the use of two relative paths to combine. The result will be written to a
+ * buffer, which might be truncated if the buffer is not large enough to hold
+ * the full path. However, the truncated result will always be null-terminated.
+ * The returned value is the amount of characters which the resulting path would
+ * take if it was not truncated (excluding the null-terminating character).
+ *
+ * @param path_a The first path which comes first.
+ * @param path_b The second path which comes after the first.
+ * @param buffer The buffer where the result will be written to.
+ * @param buffer_size The size of the result buffer.
+ * @return Returns the total amount of characters of the full, combined path.
+ */
+size_t cwk_path_join(const char *path_a, const char *path_b, char *buffer,
+ size_t buffer_size);
+
+/**
+ * @brief Joins multiple paths together.
+ *
+ * This function generates a new path by joining multiple paths together. It
+ * will remove double separators, and unlike cwk_path_get_absolute it permits
+ * the use of multiple relative paths to combine. The last path of the submitted
+ * string array must be set to NULL. The result will be written to a buffer,
+ * which might be truncated if the buffer is not large enough to hold the full
+ * path. However, the truncated result will always be null-terminated. The
+ * returned value is the amount of characters which the resulting path would
+ * take if it was not truncated (excluding the null-terminating character).
+ *
+ * @param paths An array of paths which will be joined.
+ * @param buffer The buffer where the result will be written to.
+ * @param buffer_size The size of the result buffer.
+ * @return Returns the total amount of characters of the full, combined path.
+ */
+size_t cwk_path_join_multiple(const char **paths, char *buffer,
+ size_t buffer_size);
+
+/**
+ * @brief Determines the root of a path.
+ *
+ * This function determines the root of a path by finding it's length. The root
+ * always starts at the submitted path. If the path has no root, the length will
+ * be set to zero.
+ *
+ * @param path The path which will be inspected.
+ * @param length The output of the root length.
+ */
+void cwk_path_get_root(const char *path, size_t *length);
+
+/**
+ * @brief Changes the root of a path.
+ *
+ * This function changes the root of a path. It does not normalize the result.
+ * The result will be written to a buffer, which might be truncated if the
+ * buffer is not large enough to hold the full path. However, the truncated
+ * result will always be null-terminated. The returned value is the amount of
+ * characters which the resulting path would take if it was not truncated
+ * (excluding the null-terminating character).
+ *
+ * @param path The original path which will get a new root.
+ * @param new_root The new root which will be placed in the path.
+ * @param buffer The output buffer where the result is written to.
+ * @param buffer_size The size of the output buffer where the result is written
+ * to.
+ * @return Returns the total amount of characters of the new path.
+ */
+size_t cwk_path_change_root(const char *path, const char *new_root,
+ char *buffer, size_t buffer_size);
+
+/**
+ * @brief Determine whether the path is absolute or not.
+ *
+ * This function checks whether the path is an absolute path or not. A path is
+ * considered to be absolute if the root ends with a separator.
+ *
+ * @param path The path which will be checked.
+ * @return Returns true if the path is absolute or false otherwise.
+ */
+bool cwk_path_is_absolute(const char *path);
+
+/**
+ * @brief Determine whether the path is relative or not.
+ *
+ * This function checks whether the path is a relative path or not. A path is
+ * considered to be relative if the root does not end with a separator.
+ *
+ * @param path The path which will be checked.
+ * @return Returns true if the path is relative or false otherwise.
+ */
+bool cwk_path_is_relative(const char *path);
+
+/**
+ * @brief Gets the basename of a file path.
+ *
+ * This function gets the basename of a file path. A pointer to the beginning of
+ * the basename will be returned through the basename parameter. This pointer
+ * will be positioned on the first letter after the separator. The length of the
+ * file path will be returned through the length parameter. The length will be
+ * set to zero and the basename to NULL if there is no basename available.
+ *
+ * @param path The path which will be inspected.
+ * @param basename The output of the basename pointer.
+ * @param length The output of the length of the basename.
+ */
+void cwk_path_get_basename(const char *path, const char **basename,
+ size_t *length);
+
+/**
+ * @brief Changes the basename of a file path.
+ *
+ * This function changes the basename of a file path. This function will not
+ * write out more than the specified buffer can contain. However, the generated
+ * string is always null-terminated - even if not the whole path is written out.
+ * The function returns the total number of characters the complete buffer would
+ * have, even if it was not written out completely. The path may be the same
+ * memory address as the buffer.
+ *
+ * @param path The original path which will be used for the modified path.
+ * @param new_basename The new basename which will replace the old one.
+ * @param buffer The buffer where the changed path will be written to.
+ * @param buffer_size The size of the result buffer where the changed path is
+ * written to.
+ * @return Returns the size which the complete new path would have if it was not
+ * truncated.
+ */
+size_t cwk_path_change_basename(const char *path, const char *new_basename,
+ char *buffer, size_t buffer_size);
+
+/**
+ * @brief Gets the dirname of a file path.
+ *
+ * This function determines the dirname of a file path and returns the length up
+ * to which character is considered to be part of it. If no dirname is found,
+ * the length will be set to zero. The beginning of the dirname is always equal
+ * to the submitted path pointer.
+ *
+ * @param path The path which will be inspected.
+ * @param length The length of the dirname.
+ */
+void cwk_path_get_dirname(const char *path, size_t *length);
+
+/**
+ * @brief Gets the extension of a file path.
+ *
+ * This function extracts the extension portion of a file path. A pointer to
+ * the beginning of the extension will be returned through the extension
+ * parameter if an extension is found and true is returned. This pointer will be
+ * positioned on the dot. The length of the extension name will be returned
+ * through the length parameter. If no extension is found both parameters won't
+ * be touched and false will be returned.
+ *
+ * @param path The path which will be inspected.
+ * @param extension The output of the extension pointer.
+ * @param length The output of the length of the extension.
+ * @return Returns true if an extension is found or false otherwise.
+ */
+bool cwk_path_get_extension(const char *path, const char **extension,
+ size_t *length);
+
+/**
+ * @brief Determines whether the file path has an extension.
+ *
+ * This function determines whether the submitted file path has an extension.
+ * This will evaluate to true if the last segment of the path contains a dot.
+ *
+ * @param path The path which will be inspected.
+ * @return Returns true if the path has an extension or false otherwise.
+ */
+bool cwk_path_has_extension(const char *path);
+
+/**
+ * @brief Changes the extension of a file path.
+ *
+ * This function changes the extension of a file name. The function will append
+ * an extension if the basename does not have an extension, or use the extension
+ * as a basename if the path does not have a basename. This function will not
+ * write out more than the specified buffer can contain. However, the generated
+ * string is always null-terminated - even if not the whole path is written out.
+ * The function returns the total number of characters the complete buffer would
+ * have, even if it was not written out completely. The path may be the same
+ * memory address as the buffer.
+ *
+ * @param path The path which will be used to make the change.
+ * @param new_extension The extension which will be placed within the new path.
+ * @param buffer The output buffer where the result will be written to.
+ * @param buffer_size The size of the output buffer where the result will be
+ * written to.
+ * @return Returns the total size which the output would have if it was not
+ * truncated.
+ */
+size_t cwk_path_change_extension(const char *path, const char *new_extension,
+ char *buffer, size_t buffer_size);
+
+/**
+ * @brief Creates a normalized version of the path.
+ *
+ * This function creates a normalized version of the path within the specified
+ * buffer. This function will not write out more than the specified buffer can
+ * contain. However, the generated string is always null-terminated - even if
+ * not the whole path is written out. The function returns the total number of
+ * characters the complete buffer would have, even if it was not written out
+ * completely. The path may be the same memory address as the buffer.
+ *
+ * The following will be true for the normalized path:
+ * 1) "../" will be resolved.
+ * 2) "./" will be removed.
+ * 3) double separators will be fixed with a single separator.
+ * 4) separator suffixes will be removed.
+ *
+ * @param path The path which will be normalized.
+ * @param buffer The buffer where the new path is written to.
+ * @param buffer_size The size of the buffer.
+ * @return The size which the complete normalized path has if it was not
+ * truncated.
+ */
+size_t cwk_path_normalize(const char *path, char *buffer, size_t buffer_size);
+
+/**
+ * @brief Finds common portions in two paths.
+ *
+ * This function finds common portions in two paths and returns the number
+ * characters from the beginning of the base path which are equal to the other
+ * path.
+ *
+ * @param path_base The base path which will be compared with the other path.
+ * @param path_other The other path which will compared with the base path.
+ * @return Returns the number of characters which are common in the base path.
+ */
+size_t cwk_path_get_intersection(const char *path_base, const char *path_other);
+
+/**
+ * @brief Gets the first segment of a path.
+ *
+ * This function finds the first segment of a path. The position of the segment
+ * is set to the first character after the separator, and the length counts all
+ * characters until the next separator (excluding the separator).
+ *
+ * @param path The path which will be inspected.
+ * @param segment The segment which will be extracted.
+ * @return Returns true if there is a segment or false if there is none.
+ */
+bool cwk_path_get_first_segment(const char *path, struct cwk_segment *segment);
+
+/**
+ * @brief Gets the last segment of the path.
+ *
+ * This function gets the last segment of a path. This function may return false
+ * if the path doesn't contain any segments, in which case the submitted segment
+ * parameter is not modified. The position of the segment is set to the first
+ * character after the separator, and the length counts all characters until the
+ * end of the path (excluding the separator).
+ *
+ * @param path The path which will be inspected.
+ * @param segment The segment which will be extracted.
+ * @return Returns true if there is a segment or false if there is none.
+ */
+bool cwk_path_get_last_segment(const char *path, struct cwk_segment *segment);
+
+/**
+ * @brief Advances to the next segment.
+ *
+ * This function advances the current segment to the next segment. If there are
+ * no more segments left, the submitted segment structure will stay unchanged
+ * and false is returned.
+ *
+ * @param segment The current segment which will be advanced to the next one.
+ * @return Returns true if another segment was found or false otherwise.
+ */
+bool cwk_path_get_next_segment(struct cwk_segment *segment);
+
+/**
+ * @brief Moves to the previous segment.
+ *
+ * This function moves the current segment to the previous segment. If the
+ * current segment is the first one, the submitted segment structure will stay
+ * unchanged and false is returned.
+ *
+ * @param segment The current segment which will be moved to the previous one.
+ * @return Returns true if there is a segment before this one or false
+ * otherwise.
+ */
+bool cwk_path_get_previous_segment(struct cwk_segment *segment);
+
+/**
+ * @brief Gets the type of the submitted path segment.
+ *
+ * This function inspects the contents of the segment and determines the type of
+ * it. Currently, there are three types CWK_NORMAL, CWK_CURRENT and CWK_BACK. A
+ * CWK_NORMAL segment is a normal folder or file entry. A CWK_CURRENT is a "./"
+ * and a CWK_BACK a "../" segment.
+ *
+ * @param segment The segment which will be inspected.
+ * @return Returns the type of the segment.
+ */
+enum cwk_segment_type cwk_path_get_segment_type(
+ const struct cwk_segment *segment);
+
+/**
+ * @brief Changes the content of a segment.
+ *
+ * This function overrides the content of a segment to the submitted value and
+ * outputs the whole new path to the submitted buffer. The result might require
+ * less or more space than before if the new value length differs from the
+ * original length. The output is truncated if the new path is larger than the
+ * submitted buffer size, but it is always null-terminated. The source of the
+ * segment and the submitted buffer may be the same.
+ *
+ * @param segment The segment which will be modifier.
+ * @param value The new content of the segment.
+ * @param buffer The buffer where the modified path will be written to.
+ * @param buffer_size The size of the output buffer.
+ * @return Returns the total size which would have been written if the output
+ * was not truncated.
+ */
+size_t cwk_path_change_segment(struct cwk_segment *segment, const char *value,
+ char *buffer, size_t buffer_size);
+
+/**
+ * @brief Checks whether the submitted pointer points to a separator.
+ *
+ * This function simply checks whether the submitted pointer points to a
+ * separator, which has to be null-terminated (but not necessarily after the
+ * separator). The function will return true if it is a separator, or false
+ * otherwise.
+ *
+ * @param symbol A pointer to a string.
+ * @return Returns true if it is a separator, or false otherwise.
+ */
+bool cwk_path_is_separator(const char *str);
+
+/**
+ * @brief Guesses the path style.
+ *
+ * This function guesses the path style based on a submitted path-string. The
+ * guessing will look at the root and the type of slashes contained in the path
+ * and return the style which is more likely used in the path.
+ *
+ * @param path The path which will be inspected.
+ * @return Returns the style which is most likely used for the path.
+ */
+enum cwk_path_style cwk_path_guess_style(const char *path);
+
+/**
+ * @brief Configures which path style is used.
+ *
+ * This function configures which path style is used. The following styles are
+ * currently supported.
+ *
+ * CWK_STYLE_WINDOWS: Use backslashes as a separator and volume for the root.
+ * CWK_STYLE_UNIX: Use slashes as a separator and a slash for the root.
+ *
+ * @param style The style which will be used from now on.
+ */
+void cwk_path_set_style(enum cwk_path_style style);
+
+/**
+ * @brief Gets the path style configuration.
+ *
+ * This function gets the style configuration which is currently used for the
+ * paths. This configuration determines how paths are parsed and generated.
+ *
+ * @return Returns the current path style configuration.
+ */
+enum cwk_path_style cwk_path_get_style(void);
+
+#endif
diff --git a/src/minivhd/libxml2_encoding.c b/src/minivhd/libxml2_encoding.c
new file mode 100644
index 0000000..1c9575b
--- /dev/null
+++ b/src/minivhd/libxml2_encoding.c
@@ -0,0 +1,447 @@
+/*
+ * encoding.c : implements the encoding conversion functions needed for XML
+ *
+ * Related specs:
+ * rfc2044 (UTF-8 and UTF-16) F. Yergeau Alis Technologies
+ * rfc2781 UTF-16, an encoding of ISO 10646, P. Hoffman, F. Yergeau
+ * [ISO-10646] UTF-8 and UTF-16 in Annexes
+ * [ISO-8859-1] ISO Latin-1 characters codes.
+ * [UNICODE] The Unicode Consortium, "The Unicode Standard --
+ * Worldwide Character Encoding -- Version 1.0", Addison-
+ * Wesley, Volume 1, 1991, Volume 2, 1992. UTF-8 is
+ * described in Unicode Technical Report #4.
+ * [US-ASCII] Coded Character Set--7-bit American Standard Code for
+ * Information Interchange, ANSI X3.4-1986.
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ *
+ * Original code for IsoLatin1 and UTF-16 by "Martin J. Duerst"
+ *
+ * Adapted and abridged for MiniVHD by Sherman Perry
+ */
+#include
+
+static int xmlLittleEndian = 1;
+
+/* Note: extracted from original 'void xmlInitCharEncodingHandlers(void)' function */
+void xmlEncodingInit(void)
+{
+ unsigned short int tst = 0x1234;
+ unsigned char *ptr = (unsigned char *) &tst;
+
+ if (*ptr == 0x12) xmlLittleEndian = 0;
+ else if (*ptr == 0x34) xmlLittleEndian = 1;
+}
+
+/**
+ * UTF16LEToUTF8:
+ * @out: a pointer to an array of bytes to store the result
+ * @outlen: the length of @out
+ * @inb: a pointer to an array of UTF-16LE passwd as a byte array
+ * @inlenb: the length of @in in UTF-16LE chars
+ *
+ * Take a block of UTF-16LE ushorts in and try to convert it to an UTF-8
+ * block of chars out. This function assumes the endian property
+ * is the same between the native type of this machine and the
+ * inputed one.
+ *
+ * Returns the number of bytes written, or -1 if lack of space, or -2
+ * if the transcoding fails (if *in is not a valid utf16 string)
+ * The value of *inlen after return is the number of octets consumed
+ * if the return value is positive, else unpredictable.
+ */
+int UTF16LEToUTF8(unsigned char* out, int *outlen,
+ const unsigned char* inb, int *inlenb)
+{
+ unsigned char* outstart = out;
+ const unsigned char* processed = inb;
+ unsigned char* outend = out + *outlen;
+ unsigned short* in = (unsigned short*) inb;
+ unsigned short* inend;
+ unsigned int c, d, inlen;
+ unsigned char *tmp;
+ int bits;
+
+ if ((*inlenb % 2) == 1)
+ (*inlenb)--;
+ inlen = *inlenb / 2;
+ inend = in + inlen;
+ while ((in < inend) && (out - outstart + 5 < *outlen)) {
+ if (xmlLittleEndian) {
+ c= *in++;
+ } else {
+ tmp = (unsigned char *) in;
+ c = *tmp++;
+ c = c | (((unsigned int)*tmp) << 8);
+ in++;
+ }
+ if ((c & 0xFC00) == 0xD800) { /* surrogates */
+ if (in >= inend) { /* (in > inend) shouldn't happens */
+ break;
+ }
+ if (xmlLittleEndian) {
+ d = *in++;
+ } else {
+ tmp = (unsigned char *) in;
+ d = *tmp++;
+ d = d | (((unsigned int)*tmp) << 8);
+ in++;
+ }
+ if ((d & 0xFC00) == 0xDC00) {
+ c &= 0x03FF;
+ c <<= 10;
+ c |= d & 0x03FF;
+ c += 0x10000;
+ }
+ else {
+ *outlen = out - outstart;
+ *inlenb = processed - inb;
+ return(-2);
+ }
+ }
+
+ /* assertion: c is a single UTF-4 value */
+ if (out >= outend)
+ break;
+ if (c < 0x80) { *out++= c; bits= -6; }
+ else if (c < 0x800) { *out++= ((c >> 6) & 0x1F) | 0xC0; bits= 0; }
+ else if (c < 0x10000) { *out++= ((c >> 12) & 0x0F) | 0xE0; bits= 6; }
+ else { *out++= ((c >> 18) & 0x07) | 0xF0; bits= 12; }
+
+ for ( ; bits >= 0; bits-= 6) {
+ if (out >= outend)
+ break;
+ *out++= ((c >> bits) & 0x3F) | 0x80;
+ }
+ processed = (const unsigned char*) in;
+ }
+ *outlen = out - outstart;
+ *inlenb = processed - inb;
+ return(*outlen);
+}
+
+/**
+ * UTF8ToUTF16LE:
+ * @outb: a pointer to an array of bytes to store the result
+ * @outlen: the length of @outb
+ * @in: a pointer to an array of UTF-8 chars
+ * @inlen: the length of @in
+ *
+ * Take a block of UTF-8 chars in and try to convert it to an UTF-16LE
+ * block of chars out.
+ *
+ * Returns the number of bytes written, or -1 if lack of space, or -2
+ * if the transcoding failed.
+ */
+int UTF8ToUTF16LE(unsigned char* outb, int *outlen,
+ const unsigned char* in, int *inlen)
+{
+ unsigned short* out = (unsigned short*) outb;
+ const unsigned char* processed = in;
+ const unsigned char *const instart = in;
+ unsigned short* outstart= out;
+ unsigned short* outend;
+ const unsigned char* inend;
+ unsigned int c, d;
+ int trailing;
+ unsigned char *tmp;
+ unsigned short tmp1, tmp2;
+
+ /* UTF16LE encoding has no BOM */
+ if ((out == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1);
+ if (in == NULL) {
+ *outlen = 0;
+ *inlen = 0;
+ return(0);
+ }
+ inend= in + *inlen;
+ outend = out + (*outlen / 2);
+ while (in < inend) {
+ d= *in++;
+ if (d < 0x80) { c= d; trailing= 0; }
+ else if (d < 0xC0) {
+ /* trailing byte in leading position */
+ *outlen = (out - outstart) * 2;
+ *inlen = processed - instart;
+ return(-2);
+ } else if (d < 0xE0) { c= d & 0x1F; trailing= 1; }
+ else if (d < 0xF0) { c= d & 0x0F; trailing= 2; }
+ else if (d < 0xF8) { c= d & 0x07; trailing= 3; }
+ else {
+ /* no chance for this in UTF-16 */
+ *outlen = (out - outstart) * 2;
+ *inlen = processed - instart;
+ return(-2);
+ }
+
+ if (inend - in < trailing) {
+ break;
+ }
+
+ for ( ; trailing; trailing--) {
+ if ((in >= inend) || (((d= *in++) & 0xC0) != 0x80))
+ break;
+ c <<= 6;
+ c |= d & 0x3F;
+ }
+
+ /* assertion: c is a single UTF-4 value */
+ if (c < 0x10000) {
+ if (out >= outend)
+ break;
+ if (xmlLittleEndian) {
+ *out++ = c;
+ } else {
+ tmp = (unsigned char *) out;
+ *tmp = c ;
+ *(tmp + 1) = c >> 8 ;
+ out++;
+ }
+ }
+ else if (c < 0x110000) {
+ if (out+1 >= outend)
+ break;
+ c -= 0x10000;
+ if (xmlLittleEndian) {
+ *out++ = 0xD800 | (c >> 10);
+ *out++ = 0xDC00 | (c & 0x03FF);
+ } else {
+ tmp1 = 0xD800 | (c >> 10);
+ tmp = (unsigned char *) out;
+ *tmp = (unsigned char) tmp1;
+ *(tmp + 1) = tmp1 >> 8;
+ out++;
+
+ tmp2 = 0xDC00 | (c & 0x03FF);
+ tmp = (unsigned char *) out;
+ *tmp = (unsigned char) tmp2;
+ *(tmp + 1) = tmp2 >> 8;
+ out++;
+ }
+ }
+ else
+ break;
+ processed = in;
+ }
+ *outlen = (out - outstart) * 2;
+ *inlen = processed - instart;
+ return(*outlen);
+}
+
+/**
+ * UTF16BEToUTF8:
+ * @out: a pointer to an array of bytes to store the result
+ * @outlen: the length of @out
+ * @inb: a pointer to an array of UTF-16 passed as a byte array
+ * @inlenb: the length of @in in UTF-16 chars
+ *
+ * Take a block of UTF-16 ushorts in and try to convert it to an UTF-8
+ * block of chars out. This function assumes the endian property
+ * is the same between the native type of this machine and the
+ * inputed one.
+ *
+ * Returns the number of bytes written, or -1 if lack of space, or -2
+ * if the transcoding fails (if *in is not a valid utf16 string)
+ * The value of *inlen after return is the number of octets consumed
+ * if the return value is positive, else unpredictable.
+ */
+int UTF16BEToUTF8(unsigned char* out, int *outlen,
+ const unsigned char* inb, int *inlenb)
+{
+ unsigned char* outstart = out;
+ const unsigned char* processed = inb;
+ unsigned char* outend = out + *outlen;
+ unsigned short* in = (unsigned short*) inb;
+ unsigned short* inend;
+ unsigned int c, d, inlen;
+ unsigned char *tmp;
+ int bits;
+
+ if ((*inlenb % 2) == 1)
+ (*inlenb)--;
+ inlen = *inlenb / 2;
+ inend= in + inlen;
+ while (in < inend) {
+ if (xmlLittleEndian) {
+ tmp = (unsigned char *) in;
+ c = *tmp++;
+ c = c << 8;
+ c = c | (unsigned int) *tmp;
+ in++;
+ } else {
+ c= *in++;
+ }
+ if ((c & 0xFC00) == 0xD800) { /* surrogates */
+ if (in >= inend) { /* (in > inend) shouldn't happens */
+ *outlen = out - outstart;
+ *inlenb = processed - inb;
+ return(-2);
+ }
+ if (xmlLittleEndian) {
+ tmp = (unsigned char *) in;
+ d = *tmp++;
+ d = d << 8;
+ d = d | (unsigned int) *tmp;
+ in++;
+ } else {
+ d= *in++;
+ }
+ if ((d & 0xFC00) == 0xDC00) {
+ c &= 0x03FF;
+ c <<= 10;
+ c |= d & 0x03FF;
+ c += 0x10000;
+ }
+ else {
+ *outlen = out - outstart;
+ *inlenb = processed - inb;
+ return(-2);
+ }
+ }
+
+ /* assertion: c is a single UTF-4 value */
+ if (out >= outend)
+ break;
+ if (c < 0x80) { *out++= c; bits= -6; }
+ else if (c < 0x800) { *out++= ((c >> 6) & 0x1F) | 0xC0; bits= 0; }
+ else if (c < 0x10000) { *out++= ((c >> 12) & 0x0F) | 0xE0; bits= 6; }
+ else { *out++= ((c >> 18) & 0x07) | 0xF0; bits= 12; }
+
+ for ( ; bits >= 0; bits-= 6) {
+ if (out >= outend)
+ break;
+ *out++= ((c >> bits) & 0x3F) | 0x80;
+ }
+ processed = (const unsigned char*) in;
+ }
+ *outlen = out - outstart;
+ *inlenb = processed - inb;
+ return(*outlen);
+}
+
+/**
+ * UTF8ToUTF16BE:
+ * @outb: a pointer to an array of bytes to store the result
+ * @outlen: the length of @outb
+ * @in: a pointer to an array of UTF-8 chars
+ * @inlen: the length of @in
+ *
+ * Take a block of UTF-8 chars in and try to convert it to an UTF-16BE
+ * block of chars out.
+ *
+ * Returns the number of byte written, or -1 by lack of space, or -2
+ * if the transcoding failed.
+ */
+int UTF8ToUTF16BE(unsigned char* outb, int *outlen,
+ const unsigned char* in, int *inlen)
+{
+ unsigned short* out = (unsigned short*) outb;
+ const unsigned char* processed = in;
+ const unsigned char *const instart = in;
+ unsigned short* outstart= out;
+ unsigned short* outend;
+ const unsigned char* inend;
+ unsigned int c, d;
+ int trailing;
+ unsigned char *tmp;
+ unsigned short tmp1, tmp2;
+
+ /* UTF-16BE has no BOM */
+ if ((outb == NULL) || (outlen == NULL) || (inlen == NULL)) return(-1);
+ if (in == NULL) {
+ *outlen = 0;
+ *inlen = 0;
+ return(0);
+ }
+ inend= in + *inlen;
+ outend = out + (*outlen / 2);
+ while (in < inend) {
+ d= *in++;
+ if (d < 0x80) { c= d; trailing= 0; }
+ else if (d < 0xC0) {
+ /* trailing byte in leading position */
+ *outlen = out - outstart;
+ *inlen = processed - instart;
+ return(-2);
+ } else if (d < 0xE0) { c= d & 0x1F; trailing= 1; }
+ else if (d < 0xF0) { c= d & 0x0F; trailing= 2; }
+ else if (d < 0xF8) { c= d & 0x07; trailing= 3; }
+ else {
+ /* no chance for this in UTF-16 */
+ *outlen = out - outstart;
+ *inlen = processed - instart;
+ return(-2);
+ }
+
+ if (inend - in < trailing) {
+ break;
+ }
+
+ for ( ; trailing; trailing--) {
+ if ((in >= inend) || (((d= *in++) & 0xC0) != 0x80)) break;
+ c <<= 6;
+ c |= d & 0x3F;
+ }
+
+ /* assertion: c is a single UTF-4 value */
+ if (c < 0x10000) {
+ if (out >= outend) break;
+ if (xmlLittleEndian) {
+ tmp = (unsigned char *) out;
+ *tmp = c >> 8;
+ *(tmp + 1) = c;
+ out++;
+ } else {
+ *out++ = c;
+ }
+ }
+ else if (c < 0x110000) {
+ if (out+1 >= outend) break;
+ c -= 0x10000;
+ if (xmlLittleEndian) {
+ tmp1 = 0xD800 | (c >> 10);
+ tmp = (unsigned char *) out;
+ *tmp = tmp1 >> 8;
+ *(tmp + 1) = (unsigned char) tmp1;
+ out++;
+
+ tmp2 = 0xDC00 | (c & 0x03FF);
+ tmp = (unsigned char *) out;
+ *tmp = tmp2 >> 8;
+ *(tmp + 1) = (unsigned char) tmp2;
+ out++;
+ } else {
+ *out++ = 0xD800 | (c >> 10);
+ *out++ = 0xDC00 | (c & 0x03FF);
+ }
+ }
+ else
+ break;
+ processed = in;
+ }
+ *outlen = (out - outstart) * 2;
+ *inlen = processed - instart;
+ return(*outlen);
+}
+
+/* This file is licenced under the MIT licence as follows:
+
+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 fur-
+nished 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, FIT-
+NESS 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. */
diff --git a/src/minivhd/libxml2_encoding.h b/src/minivhd/libxml2_encoding.h
new file mode 100644
index 0000000..d86770b
--- /dev/null
+++ b/src/minivhd/libxml2_encoding.h
@@ -0,0 +1,12 @@
+#ifndef LIBXML2_ENCODING_H
+#define LIBXML2_ENCODING_H
+
+#include
+typedef uint16_t mvhd_utf16;
+
+void xmlEncodingInit(void);
+int UTF16LEToUTF8(unsigned char* out, int *outlen, const unsigned char* inb, int *inlenb);
+int UTF8ToUTF16LE(unsigned char* outb, int *outlen, const unsigned char* in, int *inlen);
+int UTF16BEToUTF8(unsigned char* out, int *outlen, const unsigned char* inb, int *inlenb);
+int UTF8ToUTF16BE(unsigned char* outb, int *outlen, const unsigned char* in, int *inlen);
+#endif
diff --git a/src/minivhd/minivhd.h b/src/minivhd/minivhd.h
new file mode 100644
index 0000000..aafd559
--- /dev/null
+++ b/src/minivhd/minivhd.h
@@ -0,0 +1,309 @@
+#ifndef MINIVHD_H
+#define MINIVHD_H
+
+#include
+#include
+#include
+
+extern int mvhd_errno;
+
+typedef enum MVHDError {
+ MVHD_ERR_MEM = -128,
+ MVHD_ERR_FILE,
+ MVHD_ERR_NOT_VHD,
+ MVHD_ERR_TYPE,
+ MVHD_ERR_FOOTER_CHECKSUM,
+ MVHD_ERR_SPARSE_CHECKSUM,
+ MVHD_ERR_UTF_TRANSCODING_FAILED,
+ MVHD_ERR_UTF_SIZE,
+ MVHD_ERR_PATH_REL,
+ MVHD_ERR_PATH_LEN,
+ MVHD_ERR_PAR_NOT_FOUND,
+ MVHD_ERR_INVALID_PAR_UUID,
+ MVHD_ERR_INVALID_GEOM,
+ MVHD_ERR_INVALID_SIZE,
+ MVHD_ERR_INVALID_BLOCK_SIZE,
+ MVHD_ERR_INVALID_PARAMS,
+ MVHD_ERR_CONV_SIZE,
+ MVHD_ERR_TIMESTAMP
+} MVHDError;
+
+typedef enum MVHDType {
+ MVHD_TYPE_FIXED = 2,
+ MVHD_TYPE_DYNAMIC = 3,
+ MVHD_TYPE_DIFF = 4
+} MVHDType;
+
+typedef enum MVHDBlockSize {
+ MVHD_BLOCK_DEFAULT = 0, /**< 2 MB blocks */
+ MVHD_BLOCK_SMALL = 1024, /**< 512 KB blocks */
+ MVHD_BLOCK_LARGE = 4096 /**< 2 MB blocks */
+} MVHDBlockSize;
+
+typedef struct MVHDGeom {
+ uint16_t cyl;
+ uint8_t heads;
+ uint8_t spt;
+} MVHDGeom;
+
+typedef void (*mvhd_progress_callback)(uint32_t current_sector, uint32_t total_sectors);
+
+typedef struct MVHDCreationOptions {
+ int type; /** MVHD_TYPE_FIXED, MVHD_TYPE_DYNAMIC, or MVHD_TYPE_DIFF */
+ char* path; /** Absolute path of the new VHD file */
+ char* parent_path; /** For MVHD_TYPE_DIFF, this is the absolute path of the VHD's parent. For non-diff VHDs, this should be NULL. */
+ uint64_t size_in_bytes; /** Total size of the VHD's virtual disk in bytes. Must be a multiple of 512. If 0, the size is auto-calculated from the geometry field. Ignored for MVHD_TYPE_DIFF. */
+ MVHDGeom geometry; /** The geometry of the VHD. If set to 0, the geometry is auto-calculated from the size_in_bytes field. */
+ uint32_t block_size_in_sectors; /** MVHD_BLOCK_LARGE or MVHD_BLOCK_SMALL, or 0 for the default value. The number of sectors per block. */
+ mvhd_progress_callback progress_callback; /** Optional; if not NULL, gets called to indicate progress on the creation operation. Only applies to MVHD_TYPE_FIXED. */
+} MVHDCreationOptions;
+
+typedef struct MVHDMeta MVHDMeta;
+
+/**
+ * \brief Output a string from a MiniVHD error number
+ *
+ * \param [in] err is the error number to return string from
+ *
+ * \return Error string
+ */
+const char* mvhd_strerr(MVHDError err);
+
+/**
+ * \brief A simple test to see if a given file is a VHD
+ *
+ * \param [in] f file to test
+ *
+ * \retval true if f is a VHD
+ * \retval false if f is not a VHD
+ */
+bool mvhd_file_is_vhd(FILE* f);
+
+/**
+ * \brief Open a VHD image for reading and/or writing
+ *
+ * The returned pointer contains all required values and structures (and files) to
+ * read and write to a VHD file.
+ *
+ * Remember to call mvhd_close() when you are finished.
+ *
+ * \param [in] Absolute path to VHD file. Relative path will cause issues when opening
+ * a differencing VHD file
+ * \param [in] readonly set this to true to open the VHD in a read only manner
+ * \param [out] err will be set if the VHD fails to open. Value could be one of
+ * MVHD_ERR_MEM, MVHD_ERR_FILE, MVHD_ERR_NOT_VHD, MVHD_ERR_FOOTER_CHECKSUM, MVHD_ERR_SPARSE_CHECKSUM,
+ * MVHD_ERR_TYPE, MVHD_ERR_TIMESTAMP
+ * If MVHD_ERR_FILE is set, mvhd_errno will be set to the appropriate system errno value
+ *
+ * \return MVHDMeta pointer. If NULL, check err. err may also be set to MVHD_ERR_TIMESTAMP if
+ * opening a differencing VHD.
+ */
+MVHDMeta* mvhd_open(const char* path, bool readonly, int* err);
+
+/**
+ * \brief Update the parent modified timestamp in the VHD file
+ *
+ * Differencing VHD's use a parent last modified timestamp to try and detect if the
+ * parent has been modified after the child has been created. However, this is rather
+ * fragile and can be broken by moving/copying the parent. Also, MS DiskPart does not
+ * set this timestamp in the child :(
+ *
+ * Be careful when using this function that you don't update the timestamp after the
+ * parent actually has been modified.
+ *
+ * \param [in] vhdm Differencing VHD to update.
+ * \param [out] err will be set if the timestamp could not be updated
+ *
+ * \return non-zero on error, 0 on success
+ */
+int mvhd_diff_update_par_timestamp(MVHDMeta* vhdm, int* err);
+
+/**
+ * \brief Create a fixed VHD image
+ *
+ * \param [in] path is the absolute path to the image to create
+ * \param [in] geom is the HDD geometry of the image to create. Determines final image size
+ * \param [out] err indicates what error occurred, if any
+ * \param [out] progress_callback optional; if not NULL, gets called to indicate progress on the creation operation
+ *
+ * \retval NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct
+ */
+MVHDMeta* mvhd_create_fixed(const char* path, MVHDGeom geom, int* err, mvhd_progress_callback progress_callback);
+
+/**
+ * \brief Create sparse (dynamic) VHD image.
+ *
+ * \param [in] path is the absolute path to the VHD file to create
+ * \param [in] geom is the HDD geometry of the image to create. Determines final image size
+ * \param [out] err indicates what error occurred, if any
+ *
+ * \return NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct
+ */
+MVHDMeta* mvhd_create_sparse(const char* path, MVHDGeom geom, int* err);
+
+/**
+ * \brief Create differencing VHD imagee.
+ *
+ * \param [in] path is the absolute path to the VHD file to create
+ * \param [in] par_path is the absolute path to a parent image. If NULL, a sparse image is created, otherwise create a differencing image
+ * \param [out] err indicates what error occurred, if any
+ *
+ * \return NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct
+ */
+MVHDMeta* mvhd_create_diff(const char* path, const char* par_path, int* err);
+
+/**
+ * \brief Create a VHD using the provided options
+ *
+ * Use mvhd_create_ex if you want more control over the VHD's options. For quick creation, you can use mvhd_create_fixed, mvhd_create_sparse, or mvhd_create_diff.
+ *
+ * \param [in] options the VHD creation options.
+ * \param [out] err indicates what error occurred, if any
+ *
+ * \retval NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct
+ */
+MVHDMeta* mvhd_create_ex(MVHDCreationOptions options, int* err);
+
+/**
+ * \brief Safely close a VHD image
+ *
+ * \param [in] vhdm MiniVHD data structure to close
+ */
+void mvhd_close(MVHDMeta* vhdm);
+
+/**
+ * \brief Calculate hard disk geometry from a provided size
+ *
+ * The VHD format uses Cylinder, Heads, Sectors per Track (CHS) when accessing the disk.
+ * The size of the disk can be determined from C * H * S * sector_size.
+ *
+ * Note, maximum geometry size (in bytes) is 65535 * 16 * 255 * 512, which is 127GB.
+ * However, the maximum VHD size is 2040GB. For VHDs larger than 127GB, the geometry size will be
+ * smaller than the actual VHD size.
+ *
+ * This function determines the appropriate CHS geometry from a provided size in bytes.
+ * The calculations used are those provided in "Appendix: CHS Calculation" from the document
+ * "Virtual Hard Disk Image Format Specification" provided by Microsoft.
+ *
+ * \param [in] size the desired VHD image size, in bytes
+ *
+ * \return MVHDGeom the calculated geometry. This can be used in the appropriate create functions.
+ */
+MVHDGeom mvhd_calculate_geometry(uint64_t size);
+
+/**
+ * \brief Get the CHS geometry from the image
+ *
+ * \param [in] vhdm MiniVHD data structure
+ *
+ * \return The CHS geometry as stored in the image
+ */
+MVHDGeom mvhd_get_geometry(MVHDMeta* vhdm);
+
+/**
+ * \brief Get the 'current_size' value from the image
+ *
+ * Note that the size returned may not match the size calculated from the
+ * CHS geometry. It is up to the caller to decide how best to handle this.
+ *
+ * \param [in] vhdm MiniVHD data structure
+ *
+ * \return The 'current_size' value in bytes, as stored in the image.
+ * Note, this may not match the CHS geometry.
+ */
+uint64_t mvhd_get_current_size(MVHDMeta* vhdm);
+
+/**
+ * \brief Calculate CHS geometry size in bytes
+ *
+ * \param [in] geom the CHS geometry to calculate
+ *
+ * \return the size in bytes
+ */
+uint64_t mvhd_calc_size_bytes(MVHDGeom *geom);
+
+/**
+ * \brief Calculate CHS geometry size in sectors
+ *
+ * \param [in] geom the CHS geometry to calculate
+ *
+ * \return the size in sectors
+ */
+uint32_t mvhd_calc_size_sectors(MVHDGeom *geom);
+
+/**
+ * \brief Convert a raw disk image to a fixed VHD image
+ *
+ * \param [in] utf8_raw_path is the path of the raw image to convert
+ * \param [in] utf8_vhd_path is the path of the VHD to create
+ * \param [out] err indicates what error occurred, if any
+ *
+ * \return NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct
+ */
+MVHDMeta* mvhd_convert_to_vhd_fixed(const char* utf8_raw_path, const char* utf8_vhd_path, int* err);
+
+/**
+ * \brief Convert a raw disk image to a sparse VHD image
+ *
+ * \param [in] utf8_raw_path is the path of the raw image to convert
+ * \param [in] utf8_vhd_path is the path of the VHD to create
+ * \param [out] err indicates what error occurred, if any
+ *
+ * \return NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct
+ */
+MVHDMeta* mvhd_convert_to_vhd_sparse(const char* utf8_raw_path, const char* utf8_vhd_path, int* err);
+
+/**
+ * \brief Convert a VHD image to a raw disk image
+ *
+ * \param [in] utf8_vhd_path is the path of the VHD to convert
+ * \param [in] utf8_raw_path is the path of the raw image to create
+ * \param [out] err indicates what error occurred, if any
+ *
+ * \return NULL if an error occurrs. Check value of *err for actual error. Otherwise returns the raw disk image FILE pointer
+ */
+FILE* mvhd_convert_to_raw(const char* utf8_vhd_path, const char* utf8_raw_path, int *err);
+
+/**
+ * \brief Read sectors from VHD file
+ *
+ * Read num_sectors, beginning at offset from the VHD file into a buffer
+ *
+ * \param [in] vhdm MiniVHD data structure
+ * \param [in] offset the sector offset from which to start reading from
+ * \param [in] num_sectors the number of sectors to read
+ * \param [out] out_buff the buffer to write sector data to
+ *
+ * \return the number of sectors that were not read, or zero
+ */
+int mvhd_read_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff);
+
+/**
+ * \brief Write sectors to VHD file
+ *
+ * Write num_sectors, beginning at offset from a buffer VHD file into the VHD file
+ *
+ * \param [in] vhdm MiniVHD data structure
+ * \param [in] offset the sector offset from which to start writing to
+ * \param [in] num_sectors the number of sectors to write
+ * \param [in] in_buffer the buffer to write sector data to
+ *
+ * \return the number of sectors that were not written, or zero
+ */
+int mvhd_write_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff);
+
+/**
+ * \brief Write zeroed sectors to VHD file
+ *
+ * Write num_sectors, beginning at offset, of zero data into the VHD file.
+ * We reuse the existing write functions, with a preallocated zero buffer as
+ * our source buffer.
+ *
+ * \param [in] vhdm MiniVHD data structure
+ * \param [in] offset the sector offset from which to start writing to
+ * \param [in] num_sectors the number of sectors to write
+ *
+ * \return the number of sectors that were not written, or zero
+ */
+int mvhd_format_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors);
+#endif
diff --git a/src/minivhd/minivhd_convert.c b/src/minivhd/minivhd_convert.c
new file mode 100644
index 0000000..1b4f4f0
--- /dev/null
+++ b/src/minivhd/minivhd_convert.c
@@ -0,0 +1,108 @@
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+#include
+#include
+#include
+#include
+#include
+#include "minivhd_create.h"
+#include "minivhd_internal.h"
+#include "minivhd_util.h"
+#include "minivhd.h"
+
+static FILE* mvhd_open_existing_raw_img(const char* utf8_raw_path, MVHDGeom* geom, int* err);
+
+static FILE* mvhd_open_existing_raw_img(const char* utf8_raw_path, MVHDGeom* geom, int* err) {
+ FILE *raw_img = mvhd_fopen(utf8_raw_path, "rb", err);
+ if (raw_img == NULL) {
+ *err = MVHD_ERR_FILE;
+ return NULL;
+ }
+ if (geom == NULL) {
+ *err = MVHD_ERR_INVALID_GEOM;
+ return NULL;
+ }
+ mvhd_fseeko64(raw_img, 0, SEEK_END);
+ uint64_t size_bytes = (uint64_t)mvhd_ftello64(raw_img);
+ MVHDGeom new_geom = mvhd_calculate_geometry(size_bytes);
+ if (mvhd_calc_size_bytes(&new_geom) != size_bytes) {
+ *err = MVHD_ERR_CONV_SIZE;
+ return NULL;
+ }
+ geom->cyl = new_geom.cyl;
+ geom->heads = new_geom.heads;
+ geom->spt = new_geom.spt;
+ mvhd_fseeko64(raw_img, 0, SEEK_SET);
+ return raw_img;
+}
+
+MVHDMeta* mvhd_convert_to_vhd_fixed(const char* utf8_raw_path, const char* utf8_vhd_path, int* err) {
+ MVHDGeom geom;
+ FILE *raw_img = mvhd_open_existing_raw_img(utf8_raw_path, &geom, err);
+ if (raw_img == NULL) {
+ return NULL;
+ }
+ uint64_t size_in_bytes = mvhd_calc_size_bytes(&geom);
+ MVHDMeta *vhdm = mvhd_create_fixed_raw(utf8_vhd_path, raw_img, size_in_bytes, &geom, err, NULL);
+ if (vhdm == NULL) {
+ return NULL;
+ }
+ return vhdm;
+}
+MVHDMeta* mvhd_convert_to_vhd_sparse(const char* utf8_raw_path, const char* utf8_vhd_path, int* err) {
+ MVHDGeom geom;
+ MVHDMeta *vhdm = NULL;
+ FILE *raw_img = mvhd_open_existing_raw_img(utf8_raw_path, &geom, err);
+ if (raw_img == NULL) {
+ return NULL;
+ }
+ vhdm = mvhd_create_sparse(utf8_vhd_path, geom, err);
+ if (vhdm == NULL) {
+ goto end;
+ }
+ uint8_t buff[4096] = {0}; // 8 sectors
+ uint8_t empty_buff[4096] = {0};
+ int total_sectors = mvhd_calc_size_sectors(&geom);
+ int copy_sect = 0, i;
+ for (i = 0; i < total_sectors; i += 8) {
+ copy_sect = 8;
+ if ((i + 8) >= total_sectors) {
+ copy_sect = total_sectors - i;
+ memset(buff, 0, sizeof buff);
+ }
+ fread(buff, MVHD_SECTOR_SIZE, copy_sect, raw_img);
+ /* Only write data if there's data to write, to take advantage of the sparse VHD format */
+ if (memcmp(buff, empty_buff, sizeof buff) != 0) {
+ mvhd_write_sectors(vhdm, i, copy_sect, buff);
+ }
+ }
+end:
+ fclose(raw_img);
+ return vhdm;
+}
+FILE* mvhd_convert_to_raw(const char* utf8_vhd_path, const char* utf8_raw_path, int *err) {
+ FILE *raw_img = mvhd_fopen(utf8_raw_path, "wb", err);
+ if (raw_img == NULL) {
+ return NULL;
+ }
+ MVHDMeta *vhdm = mvhd_open(utf8_vhd_path, true, err);
+ if (vhdm == NULL) {
+ fclose(raw_img);
+ return NULL;
+ }
+ uint8_t buff[4096] = {0}; // 8 sectors
+ int total_sectors = mvhd_calc_size_sectors((MVHDGeom*)&vhdm->footer.geom);
+ int copy_sect = 0, i;
+ for (i = 0; i < total_sectors; i += 8) {
+ copy_sect = 8;
+ if ((i + 8) >= total_sectors) {
+ copy_sect = total_sectors - i;
+ }
+ mvhd_read_sectors(vhdm, i, copy_sect, buff);
+ fwrite(buff, MVHD_SECTOR_SIZE, copy_sect, raw_img);
+ }
+ mvhd_close(vhdm);
+ mvhd_fseeko64(raw_img, 0, SEEK_SET);
+ return raw_img;
+}
diff --git a/src/minivhd/minivhd_create.c b/src/minivhd/minivhd_create.c
new file mode 100644
index 0000000..9bb63c1
--- /dev/null
+++ b/src/minivhd/minivhd_create.c
@@ -0,0 +1,488 @@
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+#include
+#include
+#include
+#include
+#include
+#include "cwalk.h"
+#include "libxml2_encoding.h"
+#include "minivhd_internal.h"
+#include "minivhd_util.h"
+#include "minivhd_struct_rw.h"
+#include "minivhd_io.h"
+#include "minivhd_create.h"
+#include "minivhd.h"
+
+static void mvhd_gen_footer(MVHDFooter* footer, uint64_t size_in_bytes, MVHDGeom* geom, MVHDType type, uint64_t sparse_header_off);
+static void mvhd_gen_sparse_header(MVHDSparseHeader* header, uint32_t num_blks, uint64_t bat_offset, uint32_t block_size_in_sectors);
+static int mvhd_gen_par_loc(MVHDSparseHeader* header,
+ const char* child_path,
+ const char* par_path,
+ uint64_t start_offset,
+ mvhd_utf16* w2ku_path_buff,
+ mvhd_utf16* w2ru_path_buff,
+ MVHDError* err);
+static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, uint64_t size_in_bytes, MVHDGeom* geom, uint32_t block_size_in_sectors, int* err);
+
+/**
+ * \brief Populate a VHD footer
+ *
+ * \param [in] footer to populate
+ * \param [in] size_in_bytes is the total size of the virtual hard disk in bytes
+ * \param [in] geom to use
+ * \param [in] type of HVD that is being created
+ * \param [in] sparse_header_off, an absolute file offset to the sparse header. Not used for fixed VHD images
+ */
+static void mvhd_gen_footer(MVHDFooter* footer, uint64_t size_in_bytes, MVHDGeom* geom, MVHDType type, uint64_t sparse_header_off) {
+ memcpy(footer->cookie, "conectix", sizeof footer->cookie);
+ footer->features = 0x00000002;
+ footer->fi_fmt_vers = 0x00010000;
+ footer->data_offset = (type == MVHD_TYPE_DIFF || type == MVHD_TYPE_DYNAMIC) ? sparse_header_off : 0xffffffffffffffff;
+ footer->timestamp = vhd_calc_timestamp();
+ memcpy(footer->cr_app, "mvhd", sizeof footer->cr_app);
+ footer->cr_vers = 0x000e0000;
+ memcpy(footer->cr_host_os, "Wi2k", sizeof footer->cr_host_os);
+ footer->orig_sz = footer->curr_sz = size_in_bytes;
+ footer->geom.cyl = geom->cyl;
+ footer->geom.heads = geom->heads;
+ footer->geom.spt = geom->spt;
+ footer->disk_type = type;
+ mvhd_generate_uuid(footer->uuid);
+ footer->checksum = mvhd_gen_footer_checksum(footer);
+}
+
+/**
+ * \brief Populate a VHD sparse header
+ *
+ * \param [in] header for sparse and differencing images
+ * \param [in] num_blks is the number of data blocks that the image contains
+ * \param [in] bat_offset is the absolute file offset for start of the Block Allocation Table
+ * \param [in] block_size_in_sectors is the block size in sectors.
+ */
+static void mvhd_gen_sparse_header(MVHDSparseHeader* header, uint32_t num_blks, uint64_t bat_offset, uint32_t block_size_in_sectors) {
+ memcpy(header->cookie, "cxsparse", sizeof header->cookie);
+ header->data_offset = 0xffffffffffffffff;
+ header->bat_offset = bat_offset;
+ header->head_vers = 0x00010000;
+ header->max_bat_ent = num_blks;
+ header->block_sz = block_size_in_sectors * (uint32_t)MVHD_SECTOR_SIZE;
+ header->checksum = mvhd_gen_sparse_checksum(header);
+}
+
+/**
+ * \brief Generate parent locators for differencing VHD images
+ *
+ * \param [in] header the sparse header to populate with parent locator entries
+ * \param [in] child_path is the full path to the VHD being created
+ * \param [in] par_path is the full path to the parent image
+ * \param [in] start_offset is the absolute file offset from where to start storing the entries themselves. Must be sector aligned.
+ * \param [out] w2ku_path_buff is a buffer containing the full path to the parent, encoded as UTF16-LE
+ * \param [out] w2ru_path_buff is a buffer containing the relative path to the parent, encoded as UTF16-LE
+ * \param [out] err indicates what error occurred, if any
+ *
+ * \retval 0 if success
+ * \retval < 0 if an error occurrs. Check value of *err for actual error
+ */
+static int mvhd_gen_par_loc(MVHDSparseHeader* header,
+ const char* child_path,
+ const char* par_path,
+ uint64_t start_offset,
+ mvhd_utf16* w2ku_path_buff,
+ mvhd_utf16* w2ru_path_buff,
+ MVHDError* err) {
+ /* Get our paths to store in the differencing VHD. We want both the absolute path to the parent,
+ as well as the relative path from the child VHD */
+ int rv = 0;
+ char* par_filename;
+ size_t par_fn_len;
+ char rel_path[MVHD_MAX_PATH_BYTES] = {0};
+ char child_dir[MVHD_MAX_PATH_BYTES] = {0};
+ size_t child_dir_len;
+ if (strlen(child_path) < sizeof child_dir) {
+ strcpy(child_dir, child_path);
+ } else {
+ *err = MVHD_ERR_PATH_LEN;
+ rv = -1;
+ goto end;
+ }
+ cwk_path_get_basename(par_path, (const char**)&par_filename, &par_fn_len);
+ cwk_path_get_dirname(child_dir, &child_dir_len);
+ child_dir[child_dir_len] = '\0';
+ size_t rel_len = cwk_path_get_relative(child_dir, par_path, rel_path, sizeof rel_path);
+ if (rel_len > sizeof rel_path) {
+ *err = MVHD_ERR_PATH_LEN;
+ rv = -1;
+ goto end;
+ }
+ /* We have our paths, now store the parent filename directly in the sparse header. */
+ int outlen = sizeof header->par_utf16_name;
+ int utf_ret;
+ utf_ret = UTF8ToUTF16BE((unsigned char*)header->par_utf16_name, &outlen, (const unsigned char*)par_filename, (int*)&par_fn_len);
+ if (utf_ret < 0) {
+ mvhd_set_encoding_err(utf_ret, (int*)err);
+ rv = -1;
+ goto end;
+ }
+
+ /* And encode the paths to UTF16-LE */
+ size_t par_path_len = strlen(par_path);
+ outlen = sizeof *w2ku_path_buff * MVHD_MAX_PATH_CHARS;
+ utf_ret = UTF8ToUTF16LE((unsigned char*)w2ku_path_buff, &outlen, (const unsigned char*)par_path, (int*)&par_path_len);
+ if (utf_ret < 0) {
+ mvhd_set_encoding_err(utf_ret, (int*)err);
+ rv = -1;
+ goto end;
+ }
+ int w2ku_len = utf_ret;
+ outlen = sizeof *w2ru_path_buff * MVHD_MAX_PATH_CHARS;
+ utf_ret = UTF8ToUTF16LE((unsigned char*)w2ru_path_buff, &outlen, (const unsigned char*)rel_path, (int*)&rel_len);
+ if (utf_ret < 0) {
+ mvhd_set_encoding_err(utf_ret, (int*)err);
+ rv = -1;
+ goto end;
+ }
+ int w2ru_len = utf_ret;
+ /**
+ * Finally populate the parent locaters in the sparse header.
+ * This is the information needed to find the paths saved elsewhere
+ * in the VHD image
+ */
+
+ /* Note about the plat_data_space field: The VHD spec says this field stores the number of sectors needed to store the locator path.
+ * However, Hyper-V and VPC store the number of bytes, not the number of sectors, and will refuse to open VHDs which have the
+ * number of sectors in this field.
+ * See https://stackoverflow.com/questions/40760181/mistake-in-virtual-hard-disk-image-format-specification
+ */
+ header->par_loc_entry[0].plat_code = MVHD_DIF_LOC_W2KU;
+ header->par_loc_entry[0].plat_data_len = (uint32_t)w2ku_len;
+ header->par_loc_entry[0].plat_data_offset = (uint64_t)start_offset;
+ header->par_loc_entry[0].plat_data_space = ((header->par_loc_entry[0].plat_data_len / MVHD_SECTOR_SIZE) + 1) * MVHD_SECTOR_SIZE;
+ header->par_loc_entry[1].plat_code = MVHD_DIF_LOC_W2RU;
+ header->par_loc_entry[1].plat_data_len = (uint32_t)w2ru_len;
+ header->par_loc_entry[1].plat_data_offset = (uint64_t)start_offset + ((uint64_t)header->par_loc_entry[0].plat_data_space);
+ header->par_loc_entry[1].plat_data_space = ((header->par_loc_entry[1].plat_data_len / MVHD_SECTOR_SIZE) + 1) * MVHD_SECTOR_SIZE;
+ goto end;
+
+end:
+ return rv;
+}
+
+MVHDMeta* mvhd_create_fixed(const char* path, MVHDGeom geom, int* err, mvhd_progress_callback progress_callback) {
+ uint64_t size_in_bytes = mvhd_calc_size_bytes(&geom);
+ return mvhd_create_fixed_raw(path, NULL, size_in_bytes, &geom, err, progress_callback);
+}
+
+/**
+ * \brief internal function that implements public mvhd_create_fixed() functionality
+ *
+ * Contains one more parameter than the public function, to allow using an existing
+ * raw disk image as the data source for the new fixed VHD.
+ *
+ * \param [in] raw_image file handle to a raw disk image to populate VHD
+ */
+MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t size_in_bytes, MVHDGeom* geom, int* err, mvhd_progress_callback progress_callback) {
+ uint8_t img_data[MVHD_SECTOR_SIZE] = {0};
+ uint8_t footer_buff[MVHD_FOOTER_SIZE] = {0};
+ MVHDMeta* vhdm = calloc(1, sizeof *vhdm);
+ if (vhdm == NULL) {
+ *err = MVHD_ERR_MEM;
+ goto end;
+ }
+ if (geom == NULL || (geom->cyl == 0 || geom->heads == 0 || geom->spt == 0)) {
+ *err = MVHD_ERR_INVALID_GEOM;
+ goto cleanup_vhdm;
+ }
+ FILE* f = mvhd_fopen(path, "wb+", err);
+ if (f == NULL) {
+ goto cleanup_vhdm;
+ }
+ mvhd_fseeko64(f, 0, SEEK_SET);
+ uint32_t size_sectors = (uint32_t)(size_in_bytes / MVHD_SECTOR_SIZE);
+ uint32_t s;
+ if (progress_callback)
+ progress_callback(0, size_sectors);
+ if (raw_img != NULL) {
+ mvhd_fseeko64(raw_img, 0, SEEK_END);
+ uint64_t raw_size = (uint64_t)mvhd_ftello64(raw_img);
+ MVHDGeom raw_geom = mvhd_calculate_geometry(raw_size);
+ if (mvhd_calc_size_bytes(&raw_geom) != raw_size) {
+ *err = MVHD_ERR_CONV_SIZE;
+ goto cleanup_vhdm;
+ }
+ mvhd_gen_footer(&vhdm->footer, raw_size, geom, MVHD_TYPE_FIXED, 0);
+ mvhd_fseeko64(raw_img, 0, SEEK_SET);
+ for (s = 0; s < size_sectors; s++) {
+ fread(img_data, sizeof img_data, 1, raw_img);
+ fwrite(img_data, sizeof img_data, 1, f);
+ if (progress_callback)
+ progress_callback(s + 1, size_sectors);
+ }
+ } else {
+ mvhd_gen_footer(&vhdm->footer, size_in_bytes, geom, MVHD_TYPE_FIXED, 0);
+ for (s = 0; s < size_sectors; s++) {
+ fwrite(img_data, sizeof img_data, 1, f);
+ if (progress_callback)
+ progress_callback(s + 1, size_sectors);
+ }
+ }
+ mvhd_footer_to_buffer(&vhdm->footer, footer_buff);
+ fwrite(footer_buff, sizeof footer_buff, 1, f);
+ fclose(f);
+ f = NULL;
+ free(vhdm);
+ vhdm = mvhd_open(path, false, err);
+ goto end;
+
+cleanup_vhdm:
+ free(vhdm);
+ vhdm = NULL;
+end:
+ return vhdm;
+}
+
+/**
+ * \brief Create sparse or differencing VHD image.
+ *
+ * \param [in] path is the absolute path to the VHD file to create
+ * \param [in] par_path is the absolute path to a parent image. If NULL, a sparse image is created, otherwise create a differencing image
+ * \param [in] size_in_bytes is the total size in bytes of the virtual hard disk image
+ * \param [in] geom is the HDD geometry of the image to create. Determines final image size
+ * \param [in] block_size_in_sectors is the block size in sectors
+ * \param [out] err indicates what error occurred, if any
+ *
+ * \return NULL if an error occurrs. Check value of *err for actual error. Otherwise returns pointer to a MVHDMeta struct
+ */
+static MVHDMeta* mvhd_create_sparse_diff(const char* path, const char* par_path, uint64_t size_in_bytes, MVHDGeom* geom, uint32_t block_size_in_sectors, int* err) {
+ uint8_t footer_buff[MVHD_FOOTER_SIZE] = {0};
+ uint8_t sparse_buff[MVHD_SPARSE_SIZE] = {0};
+ uint8_t bat_sect[MVHD_SECTOR_SIZE];
+ MVHDGeom par_geom = {0};
+ memset(bat_sect, 0xffffffff, sizeof bat_sect);
+ MVHDMeta* vhdm = NULL;
+ MVHDMeta* par_vhdm = NULL;
+ mvhd_utf16* w2ku_path_buff = NULL;
+ mvhd_utf16* w2ru_path_buff = NULL;
+ uint32_t par_mod_timestamp = 0;
+ if (par_path != NULL) {
+ par_mod_timestamp = mvhd_file_mod_timestamp(par_path, err);
+ if (*err != 0) {
+ goto end;
+ }
+ par_vhdm = mvhd_open(par_path, true, err);
+ if (par_vhdm == NULL) {
+ goto end;
+ }
+ }
+ vhdm = calloc(1, sizeof *vhdm);
+ if (vhdm == NULL) {
+ *err = MVHD_ERR_MEM;
+ goto cleanup_par_vhdm;
+ }
+ if (par_vhdm != NULL) {
+ /* We use the geometry from the parent VHD, not what was passed in */
+ par_geom.cyl = par_vhdm->footer.geom.cyl;
+ par_geom.heads = par_vhdm->footer.geom.heads;
+ par_geom.spt = par_vhdm->footer.geom.spt;
+ geom = &par_geom;
+ size_in_bytes = par_vhdm->footer.curr_sz;
+ } else if (geom == NULL || (geom->cyl == 0 || geom->heads == 0 || geom->spt == 0)) {
+ *err = MVHD_ERR_INVALID_GEOM;
+ goto cleanup_vhdm;
+ }
+
+ FILE* f = mvhd_fopen(path, "wb+", err);
+ if (f == NULL) {
+ goto cleanup_vhdm;
+ }
+ mvhd_fseeko64(f, 0, SEEK_SET);
+ /* Note, the sparse header follows the footer copy at the beginning of the file */
+ if (par_path == NULL) {
+ mvhd_gen_footer(&vhdm->footer, size_in_bytes, geom, MVHD_TYPE_DYNAMIC, MVHD_FOOTER_SIZE);
+ } else {
+ mvhd_gen_footer(&vhdm->footer, size_in_bytes, geom, MVHD_TYPE_DIFF, MVHD_FOOTER_SIZE);
+ }
+ mvhd_footer_to_buffer(&vhdm->footer, footer_buff);
+ /* As mentioned, start with a copy of the footer */
+ fwrite(footer_buff, sizeof footer_buff, 1, f);
+ /**
+ * Calculate the number of (2MB or 512KB) data blocks required to store the entire
+ * contents of the disk image, followed by the number of sectors the
+ * BAT occupies in the image. Note, the BAT is sector aligned, and is padded
+ * to the next sector boundary
+ * */
+ uint32_t size_in_sectors = (uint32_t)(size_in_bytes / MVHD_SECTOR_SIZE);
+ uint32_t num_blks = size_in_sectors / block_size_in_sectors;
+ if (size_in_sectors % block_size_in_sectors != 0) {
+ num_blks += 1;
+ }
+ uint32_t num_bat_sect = num_blks / MVHD_BAT_ENT_PER_SECT;
+ if (num_blks % MVHD_BAT_ENT_PER_SECT != 0) {
+ num_bat_sect += 1;
+ }
+ /* Storing the BAT directly following the footer and header */
+ uint64_t bat_offset = MVHD_FOOTER_SIZE + MVHD_SPARSE_SIZE;
+ uint64_t par_loc_offset = 0;
+
+ /**
+ * If creating a differencing VHD, populate the sparse header with additional
+ * data about the parent image, and where to find it, and it's last modified timestamp
+ * */
+ if (par_vhdm != NULL) {
+ /**
+ * Create output buffers to encode paths into.
+ * The paths are not stored directly in the sparse header, hence the need to
+ * store them in buffers to be written to the VHD image later
+ */
+ w2ku_path_buff = calloc(MVHD_MAX_PATH_CHARS, sizeof * w2ku_path_buff);
+ if (w2ku_path_buff == NULL) {
+ *err = MVHD_ERR_MEM;
+ goto end;
+ }
+ w2ru_path_buff = calloc(MVHD_MAX_PATH_CHARS, sizeof * w2ru_path_buff);
+ if (w2ru_path_buff == NULL) {
+ *err = MVHD_ERR_MEM;
+ goto end;
+ }
+ memcpy(vhdm->sparse.par_uuid, par_vhdm->footer.uuid, sizeof vhdm->sparse.par_uuid);
+ par_loc_offset = bat_offset + ((uint64_t)num_bat_sect * MVHD_SECTOR_SIZE) + (5 * MVHD_SECTOR_SIZE);
+ if (mvhd_gen_par_loc(&vhdm->sparse, path, par_path, par_loc_offset, w2ku_path_buff, w2ru_path_buff, (MVHDError*)err) < 0) {
+ goto cleanup_vhdm;
+ }
+ vhdm->sparse.par_timestamp = par_mod_timestamp;
+ }
+ mvhd_gen_sparse_header(&vhdm->sparse, num_blks, bat_offset, block_size_in_sectors);
+ mvhd_header_to_buffer(&vhdm->sparse, sparse_buff);
+ fwrite(sparse_buff, sizeof sparse_buff, 1, f);
+ /* The BAT sectors need to be filled with 0xffffffff */
+ uint32_t i;
+ for (i = 0; i < num_bat_sect; i++) {
+ fwrite(bat_sect, sizeof bat_sect, 1, f);
+ }
+ mvhd_write_empty_sectors(f, 5);
+ /**
+ * If creating a differencing VHD, the paths to the parent image need to be written
+ * tp the file. Both absolute and relative paths are written
+ * */
+ if (par_vhdm != NULL) {
+ uint64_t curr_pos = (uint64_t)mvhd_ftello64(f);
+ /* Double check my sums... */
+ assert(curr_pos == par_loc_offset);
+ /* Fill the space required for location data with zero */
+ uint8_t empty_sect[MVHD_SECTOR_SIZE] = {0};
+ int i;
+ uint32_t j;
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < (vhdm->sparse.par_loc_entry[i].plat_data_space / MVHD_SECTOR_SIZE); j++) {
+ fwrite(empty_sect, sizeof empty_sect, 1, f);
+ }
+ }
+ /* Now write the location entries */
+ mvhd_fseeko64(f, vhdm->sparse.par_loc_entry[0].plat_data_offset, SEEK_SET);
+ fwrite(w2ku_path_buff, vhdm->sparse.par_loc_entry[0].plat_data_len, 1, f);
+ mvhd_fseeko64(f, vhdm->sparse.par_loc_entry[1].plat_data_offset, SEEK_SET);
+ fwrite(w2ru_path_buff, vhdm->sparse.par_loc_entry[1].plat_data_len, 1, f);
+ /* and reset the file position to continue */
+ mvhd_fseeko64(f, vhdm->sparse.par_loc_entry[1].plat_data_offset + vhdm->sparse.par_loc_entry[1].plat_data_space, SEEK_SET);
+ mvhd_write_empty_sectors(f, 5);
+ }
+ /* And finish with the footer */
+ fwrite(footer_buff, sizeof footer_buff, 1, f);
+ fclose(f);
+ f = NULL;
+ free(vhdm);
+ vhdm = mvhd_open(path, false, err);
+ goto end;
+
+cleanup_vhdm:
+ free(vhdm);
+ vhdm = NULL;
+cleanup_par_vhdm:
+ if (par_vhdm != NULL) {
+ mvhd_close(par_vhdm);
+ }
+end:
+ free(w2ku_path_buff);
+ free(w2ru_path_buff);
+ return vhdm;
+}
+
+MVHDMeta* mvhd_create_sparse(const char* path, MVHDGeom geom, int* err) {
+ uint64_t size_in_bytes = mvhd_calc_size_bytes(&geom);
+ return mvhd_create_sparse_diff(path, NULL, size_in_bytes, &geom, MVHD_BLOCK_LARGE, err);
+}
+
+MVHDMeta* mvhd_create_diff(const char* path, const char* par_path, int* err) {
+ return mvhd_create_sparse_diff(path, par_path, 0, NULL, MVHD_BLOCK_LARGE, err);
+}
+
+MVHDMeta* mvhd_create_ex(MVHDCreationOptions options, int* err) {
+ uint32_t geom_sector_size;
+ switch (options.type)
+ {
+ case MVHD_TYPE_FIXED:
+ case MVHD_TYPE_DYNAMIC:
+ geom_sector_size = mvhd_calc_size_sectors(&(options.geometry));
+ if ((options.size_in_bytes > 0 && (options.size_in_bytes % MVHD_SECTOR_SIZE) > 0)
+ || (options.size_in_bytes > MVHD_MAX_SIZE_IN_BYTES)
+ || (options.size_in_bytes == 0 && geom_sector_size == 0))
+ {
+ *err = MVHD_ERR_INVALID_SIZE;
+ return NULL;
+ }
+
+ if (options.size_in_bytes > 0 && ((uint64_t)geom_sector_size * MVHD_SECTOR_SIZE) > options.size_in_bytes)
+ {
+ *err = MVHD_ERR_INVALID_GEOM;
+ return NULL;
+ }
+
+ if (options.size_in_bytes == 0)
+ options.size_in_bytes = (uint64_t)geom_sector_size * MVHD_SECTOR_SIZE;
+
+ if (geom_sector_size == 0)
+ options.geometry = mvhd_calculate_geometry(options.size_in_bytes);
+ break;
+ case MVHD_TYPE_DIFF:
+ if (options.parent_path == NULL)
+ {
+ *err = MVHD_ERR_FILE;
+ return NULL;
+ }
+ break;
+ default:
+ *err = MVHD_ERR_TYPE;
+ return NULL;
+ }
+
+ if (options.path == NULL)
+ {
+ *err = MVHD_ERR_FILE;
+ return NULL;
+ }
+
+ if (options.type != MVHD_TYPE_FIXED)
+ {
+ if (options.block_size_in_sectors == MVHD_BLOCK_DEFAULT)
+ options.block_size_in_sectors = MVHD_BLOCK_LARGE;
+
+ if (options.block_size_in_sectors != MVHD_BLOCK_LARGE && options.block_size_in_sectors != MVHD_BLOCK_SMALL)
+ {
+ *err = MVHD_ERR_INVALID_BLOCK_SIZE;
+ return NULL;
+ }
+ }
+
+ switch (options.type)
+ {
+ case MVHD_TYPE_FIXED:
+ return mvhd_create_fixed_raw(options.path, NULL, options.size_in_bytes, &(options.geometry), err, options.progress_callback);
+ case MVHD_TYPE_DYNAMIC:
+ return mvhd_create_sparse_diff(options.path, NULL, options.size_in_bytes, &(options.geometry), options.block_size_in_sectors, err);
+ case MVHD_TYPE_DIFF:
+ return mvhd_create_sparse_diff(options.path, options.parent_path, 0, NULL, options.block_size_in_sectors, err);
+ }
+
+ return NULL; /* Make the compiler happy */
+}
diff --git a/src/minivhd/minivhd_create.h b/src/minivhd/minivhd_create.h
new file mode 100644
index 0000000..203834a
--- /dev/null
+++ b/src/minivhd/minivhd_create.h
@@ -0,0 +1,8 @@
+#ifndef MINIVHD_CREATE_H
+#define MINIVHD_CREATE_H
+#include
+#include "minivhd.h"
+
+MVHDMeta* mvhd_create_fixed_raw(const char* path, FILE* raw_img, uint64_t size_in_bytes, MVHDGeom* geom, int* err, mvhd_progress_callback progress_callback);
+
+#endif
diff --git a/src/minivhd/minivhd_internal.h b/src/minivhd/minivhd_internal.h
new file mode 100644
index 0000000..f42ca58
--- /dev/null
+++ b/src/minivhd/minivhd_internal.h
@@ -0,0 +1,96 @@
+#ifndef MINIVHD_INTERNAL_H
+#define MINIVHD_INTERNAL_H
+#include
+#include
+#include
+#include "minivhd.h" /* Pull in the MVHDMeta typedef */
+
+#define MVHD_FOOTER_SIZE 512
+#define MVHD_SPARSE_SIZE 1024
+
+#define MVHD_SECTOR_SIZE 512
+#define MVHD_BAT_ENT_PER_SECT 128
+
+#define MVHD_MAX_SIZE_IN_BYTES 0x1fe00000000
+
+#define MVHD_SPARSE_BLK 0xffffffff
+/* For simplicity, we don't handle paths longer than this
+ * Note, this is the max path in characters, as that is what
+ * Windows uses
+ */
+#define MVHD_MAX_PATH_CHARS 260
+#define MVHD_MAX_PATH_BYTES 1040
+
+#define MVHD_DIF_LOC_W2RU 0x57327275
+#define MVHD_DIF_LOC_W2KU 0x57326B75
+
+typedef struct MVHDSectorBitmap {
+ uint8_t* curr_bitmap;
+ int sector_count;
+ int curr_block;
+} MVHDSectorBitmap;
+
+typedef struct MVHDFooter {
+ uint8_t cookie[8];
+ uint32_t features;
+ uint32_t fi_fmt_vers;
+ uint64_t data_offset;
+ uint32_t timestamp;
+ uint8_t cr_app[4];
+ uint32_t cr_vers;
+ uint8_t cr_host_os[4];
+ uint64_t orig_sz;
+ uint64_t curr_sz;
+ struct {
+ uint16_t cyl;
+ uint8_t heads;
+ uint8_t spt;
+ } geom;
+ uint32_t disk_type;
+ uint32_t checksum;
+ uint8_t uuid[16];
+ uint8_t saved_st;
+ uint8_t reserved[427];
+} MVHDFooter;
+
+typedef struct MVHDSparseHeader {
+ uint8_t cookie[8];
+ uint64_t data_offset;
+ uint64_t bat_offset;
+ uint32_t head_vers;
+ uint32_t max_bat_ent;
+ uint32_t block_sz;
+ uint32_t checksum;
+ uint8_t par_uuid[16];
+ uint32_t par_timestamp;
+ uint32_t reserved_1;
+ uint8_t par_utf16_name[512];
+ struct {
+ uint32_t plat_code;
+ uint32_t plat_data_space;
+ uint32_t plat_data_len;
+ uint32_t reserved;
+ uint64_t plat_data_offset;
+ } par_loc_entry[8];
+ uint8_t reserved_2[256];
+} MVHDSparseHeader;
+
+struct MVHDMeta {
+ FILE* f;
+ bool readonly;
+ char filename[MVHD_MAX_PATH_BYTES];
+ struct MVHDMeta* parent;
+ MVHDFooter footer;
+ MVHDSparseHeader sparse;
+ uint32_t* block_offset;
+ int sect_per_block;
+ MVHDSectorBitmap bitmap;
+ int (*read_sectors)(MVHDMeta*, uint32_t, int, void*);
+ int (*write_sectors)(MVHDMeta*, uint32_t, int, void*);
+ struct {
+ uint8_t* zero_data;
+ int sector_count;
+ } format_buffer;
+};
+
+#endif
diff --git a/src/minivhd/minivhd_io.c b/src/minivhd/minivhd_io.c
new file mode 100644
index 0000000..c21f68d
--- /dev/null
+++ b/src/minivhd/minivhd_io.c
@@ -0,0 +1,281 @@
+/**
+ * \file
+ * \brief Sector reading and writing implementations
+ */
+
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+#include
+#include
+#include "minivhd_internal.h"
+#include "minivhd_util.h"
+
+/* The following bit array macros adapted from
+ http://www.mathcs.emory.edu/~cheung/Courses/255/Syllabus/1-C-intro/bit-array.html */
+
+#define VHD_SETBIT(A,k) ( A[(k/8)] |= (0x80 >> (k%8)) )
+#define VHD_CLEARBIT(A,k) ( A[(k/8)] &= ~(0x80 >> (k%8)) )
+#define VHD_TESTBIT(A,k) ( A[(k/8)] & (0x80 >> (k%8)) )
+
+static inline void mvhd_check_sectors(uint32_t offset, int num_sectors, uint32_t total_sectors, int* transfer_sect, int* trunc_sect);
+static void mvhd_read_sect_bitmap(MVHDMeta* vhdm, int blk);
+static void mvhd_write_bat_entry(MVHDMeta* vhdm, int blk);
+static void mvhd_create_block(MVHDMeta* vhdm, int blk);
+static void mvhd_write_curr_sect_bitmap(MVHDMeta* vhdm);
+
+/**
+ * \brief Check that we will not be overflowing buffers
+ *
+ * \param [in] offset The offset from which we are beginning from
+ * \param [in] num_sectors The number of sectors which we desire to read/write
+ * \param [in] total_sectors The total number of sectors available
+ * \param [out] transfer_sect The number of sectors to actually write.
+ * This may be lower than num_sectors if offset + num_sectors >= total_sectors
+ * \param [out] trunc_sectors The number of sectors truncated if transfer_sectors < num_sectors
+ */
+static inline void mvhd_check_sectors(uint32_t offset, int num_sectors, uint32_t total_sectors, int* transfer_sect, int* trunc_sect) {
+ *transfer_sect = num_sectors;
+ *trunc_sect = 0;
+ if ((total_sectors - offset) < (uint32_t)*transfer_sect) {
+ *transfer_sect = total_sectors - offset;
+ *trunc_sect = num_sectors - *transfer_sect;
+ }
+}
+
+void mvhd_write_empty_sectors(FILE* f, int sector_count) {
+ uint8_t zero_bytes[MVHD_SECTOR_SIZE] = {0};
+ int i;
+ for (i = 0; i < sector_count; i++) {
+ fwrite(zero_bytes, sizeof zero_bytes, 1, f);
+ }
+}
+
+/**
+ * \brief Read the sector bitmap for a block.
+ *
+ * If the block is sparse, the sector bitmap in memory will be
+ * zeroed. Otherwise, the sector bitmap is read from the VHD file.
+ *
+ * \param [in] vhdm MiniVHD data structure
+ * \param [in] blk The block for which to read the sector bitmap from
+ */
+static void mvhd_read_sect_bitmap(MVHDMeta* vhdm, int blk) {
+ if (vhdm->block_offset[blk] != MVHD_SPARSE_BLK) {
+ mvhd_fseeko64(vhdm->f, (uint64_t)vhdm->block_offset[blk] * MVHD_SECTOR_SIZE, SEEK_SET);
+ fread(vhdm->bitmap.curr_bitmap, vhdm->bitmap.sector_count * MVHD_SECTOR_SIZE, 1, vhdm->f);
+ } else {
+ memset(vhdm->bitmap.curr_bitmap, 0, vhdm->bitmap.sector_count * MVHD_SECTOR_SIZE);
+ }
+ vhdm->bitmap.curr_block = blk;
+}
+
+/**
+ * \brief Write the current sector bitmap in memory to file
+ *
+ * \param [in] vhdm MiniVHD data structure
+ */
+static void mvhd_write_curr_sect_bitmap(MVHDMeta* vhdm) {
+ if (vhdm->bitmap.curr_block >= 0) {
+ int64_t abs_offset = (int64_t)vhdm->block_offset[vhdm->bitmap.curr_block] * MVHD_SECTOR_SIZE;
+ mvhd_fseeko64(vhdm->f, abs_offset, SEEK_SET);
+ fwrite(vhdm->bitmap.curr_bitmap, MVHD_SECTOR_SIZE, vhdm->bitmap.sector_count, vhdm->f);
+ }
+}
+
+/**
+ * \brief Write block offset from memory into file
+ *
+ * \param [in] vhdm MiniVHD data structure
+ * \param [in] blk The block for which to write the offset for
+ */
+static void mvhd_write_bat_entry(MVHDMeta* vhdm, int blk) {
+ uint64_t table_offset = vhdm->sparse.bat_offset + ((uint64_t)blk * sizeof *vhdm->block_offset);
+ uint32_t offset = mvhd_to_be32(vhdm->block_offset[blk]);
+ mvhd_fseeko64(vhdm->f, table_offset, SEEK_SET);
+ fwrite(&offset, sizeof offset, 1, vhdm->f);
+}
+
+/**
+ * \brief Create an empty block in a sparse or differencing VHD image
+ *
+ * VHD images store data in blocks, which are typically 4096 sectors in size
+ * (~2MB). These blocks may be stored on disk in any order. Blocks are created
+ * on demand when required.
+ *
+ * This function creates new, empty blocks, by replacing the footer at the end of the file
+ * and then re-inserting the footer at the new file end. The BAT table entry for the
+ * new block is updated with the new offset.
+ *
+ * \param [in] vhdm MiniVHD data structure
+ * \param [in] blk The block number to create
+ */
+static void mvhd_create_block(MVHDMeta* vhdm, int blk) {
+ uint8_t footer[MVHD_FOOTER_SIZE];
+ /* Seek to where the footer SHOULD be */
+ mvhd_fseeko64(vhdm->f, -MVHD_FOOTER_SIZE, SEEK_END);
+ fread(footer, sizeof footer, 1, vhdm->f);
+ mvhd_fseeko64(vhdm->f, -MVHD_FOOTER_SIZE, SEEK_END);
+ if (!mvhd_is_conectix_str(footer)) {
+ /* Oh dear. We use the header instead, since something has gone wrong at the footer */
+ mvhd_fseeko64(vhdm->f, 0, SEEK_SET);
+ fread(footer, sizeof footer, 1, vhdm->f);
+ mvhd_fseeko64(vhdm->f, 0, SEEK_END);
+ }
+ int64_t abs_offset = mvhd_ftello64(vhdm->f);
+ if (abs_offset % MVHD_SECTOR_SIZE != 0) {
+ /* Yikes! We're supposed to be on a sector boundary. Add some padding */
+ int64_t padding_amount = (int64_t)MVHD_SECTOR_SIZE - (abs_offset % MVHD_SECTOR_SIZE);
+ uint8_t zero_byte = 0;
+ int i;
+ for (i = 0; i < padding_amount; i++) {
+ fwrite(&zero_byte, sizeof zero_byte, 1, vhdm->f);
+ }
+ abs_offset += padding_amount;
+ }
+ uint32_t sect_offset = (uint32_t)(abs_offset / MVHD_SECTOR_SIZE);
+ int blk_size_sectors = vhdm->sparse.block_sz / MVHD_SECTOR_SIZE;
+ mvhd_write_empty_sectors(vhdm->f, vhdm->bitmap.sector_count + blk_size_sectors);
+ /* Add a bit of padding. That's what Windows appears to do, although it's not strictly necessary... */
+ mvhd_write_empty_sectors(vhdm->f, 5);
+ /* And we finish with the footer */
+ fwrite(footer, sizeof footer, 1, vhdm->f);
+ /* We no longer have a sparse block. Update that BAT! */
+ vhdm->block_offset[blk] = sect_offset;
+ mvhd_write_bat_entry(vhdm, blk);
+}
+
+int mvhd_fixed_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) {
+ int64_t addr;
+ int transfer_sectors, truncated_sectors;
+ uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE);
+ mvhd_check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors);
+ addr = (int64_t)offset * MVHD_SECTOR_SIZE;
+ mvhd_fseeko64(vhdm->f, addr, SEEK_SET);
+ fread(out_buff, transfer_sectors*MVHD_SECTOR_SIZE, 1, vhdm->f);
+ return truncated_sectors;
+}
+
+int mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) {
+ int transfer_sectors, truncated_sectors;
+ uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE);
+ mvhd_check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors);
+ uint8_t* buff = (uint8_t*)out_buff;
+ int64_t addr;
+ uint32_t s, ls;
+ int blk, prev_blk, sib;
+ ls = offset + transfer_sectors;
+ prev_blk = -1;
+ for (s = offset; s < ls; s++) {
+ blk = s / vhdm->sect_per_block;
+ sib = s % vhdm->sect_per_block;
+ if (blk != prev_blk) {
+ prev_blk = blk;
+ if (vhdm->bitmap.curr_block != blk) {
+ mvhd_read_sect_bitmap(vhdm, blk);
+ mvhd_fseeko64(vhdm->f, (uint64_t)sib * MVHD_SECTOR_SIZE, SEEK_CUR);
+ } else {
+ addr = ((int64_t)vhdm->block_offset[blk] + vhdm->bitmap.sector_count + sib) * MVHD_SECTOR_SIZE;
+ mvhd_fseeko64(vhdm->f, addr, SEEK_SET);
+ }
+ }
+ if (VHD_TESTBIT(vhdm->bitmap.curr_bitmap, sib)) {
+ fread(buff, MVHD_SECTOR_SIZE, 1, vhdm->f);
+ } else {
+ memset(buff, 0, MVHD_SECTOR_SIZE);
+ mvhd_fseeko64(vhdm->f, MVHD_SECTOR_SIZE, SEEK_CUR);
+ }
+ buff += MVHD_SECTOR_SIZE;
+ }
+ return truncated_sectors;
+}
+
+int mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) {
+ int transfer_sectors, truncated_sectors;
+ uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE);
+ mvhd_check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors);
+ uint8_t* buff = (uint8_t*)out_buff;
+ MVHDMeta* curr_vhdm = vhdm;
+ uint32_t s, ls;
+ int blk, sib;
+ ls = offset + transfer_sectors;
+ for (s = offset; s < ls; s++) {
+ while (curr_vhdm->footer.disk_type == MVHD_TYPE_DIFF) {
+ blk = s / curr_vhdm->sect_per_block;
+ sib = s % curr_vhdm->sect_per_block;
+ if (curr_vhdm->bitmap.curr_block != blk) {
+ mvhd_read_sect_bitmap(curr_vhdm, blk);
+ }
+ if (!VHD_TESTBIT(curr_vhdm->bitmap.curr_bitmap, sib)) {
+ curr_vhdm = curr_vhdm->parent;
+ } else { break; }
+ }
+ /* We handle actual sector reading using the fixed or sparse functions,
+ as a differencing VHD is also a sparse VHD */
+ if (curr_vhdm->footer.disk_type == MVHD_TYPE_DIFF || curr_vhdm->footer.disk_type == MVHD_TYPE_DYNAMIC) {
+ mvhd_sparse_read(curr_vhdm, s, 1, buff);
+ } else {
+ mvhd_fixed_read(curr_vhdm, s, 1, buff);
+ }
+ curr_vhdm = vhdm;
+ buff += MVHD_SECTOR_SIZE;
+ }
+ return truncated_sectors;
+}
+
+int mvhd_fixed_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) {
+ int64_t addr;
+ int transfer_sectors, truncated_sectors;
+ uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE);
+ mvhd_check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors);
+ addr = (int64_t)offset * MVHD_SECTOR_SIZE;
+ mvhd_fseeko64(vhdm->f, addr, SEEK_SET);
+ fwrite(in_buff, transfer_sectors*MVHD_SECTOR_SIZE, 1, vhdm->f);
+ return truncated_sectors;
+}
+
+int mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) {
+ int transfer_sectors, truncated_sectors;
+ uint32_t total_sectors = (uint32_t)(vhdm->footer.curr_sz / MVHD_SECTOR_SIZE);
+ mvhd_check_sectors(offset, num_sectors, total_sectors, &transfer_sectors, &truncated_sectors);
+ uint8_t* buff = (uint8_t*)in_buff;
+ int64_t addr;
+ uint32_t s, ls;
+ int blk, prev_blk, sib;
+ ls = offset + transfer_sectors;
+ prev_blk = -1;
+ for (s = offset; s < ls; s++) {
+ blk = s / vhdm->sect_per_block;
+ sib = s % vhdm->sect_per_block;
+ if (vhdm->bitmap.curr_block != blk && prev_blk >= 0) {
+ /* Write the sector bitmap for the previous block, before we replace it. */
+ mvhd_write_curr_sect_bitmap(vhdm);
+ }
+ if (vhdm->block_offset[blk] == MVHD_SPARSE_BLK) {
+ /* "read" the sector bitmap first, before creating a new block, as the bitmap will be
+ zero either way */
+ mvhd_read_sect_bitmap(vhdm, blk);
+ mvhd_create_block(vhdm, blk);
+ }
+ if (blk != prev_blk) {
+ if (vhdm->bitmap.curr_block != blk) {
+ mvhd_read_sect_bitmap(vhdm, blk);
+ mvhd_fseeko64(vhdm->f, (uint64_t)sib * MVHD_SECTOR_SIZE, SEEK_CUR);
+ } else {
+ addr = ((int64_t)vhdm->block_offset[blk] + vhdm->bitmap.sector_count + sib) * MVHD_SECTOR_SIZE;
+ mvhd_fseeko64(vhdm->f, addr, SEEK_SET);
+ }
+ prev_blk = blk;
+ }
+ fwrite(buff, MVHD_SECTOR_SIZE, 1, vhdm->f);
+ VHD_SETBIT(vhdm->bitmap.curr_bitmap, sib);
+ buff += MVHD_SECTOR_SIZE;
+ }
+ /* And write the sector bitmap for the last block we visited to disk */
+ mvhd_write_curr_sect_bitmap(vhdm);
+ return truncated_sectors;
+}
+
+int mvhd_noop_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) {
+ return 0;
+}
diff --git a/src/minivhd/minivhd_io.h b/src/minivhd/minivhd_io.h
new file mode 100644
index 0000000..0f4017a
--- /dev/null
+++ b/src/minivhd/minivhd_io.h
@@ -0,0 +1,132 @@
+#ifndef MINIVHD_IO_H
+#define MINIVHD_IO_H
+#include "minivhd.h"
+
+/**
+ * \brief Write zero filled sectors to file.
+ *
+ * Note, the caller should set the file position before calling this
+ * function for correct operation.
+ *
+ * \param [in] f File to write sectors to
+ * \param [in] sector_count The number of sectors to write
+ */
+void mvhd_write_empty_sectors(FILE* f, int sector_count);
+
+/**
+ * \brief Read a fixed VHD image
+ *
+ * Fixed VHD images are essentially raw image files with a footer tacked on
+ * the end. They are therefore straightforward to write
+ *
+ * \param [in] vhdm MiniVHD data structure
+ * \param [in] offset Sector offset to read from
+ * \param [in] num_sectors The desired number of sectors to read
+ * \param [out] out_buff An output buffer to store read sectors. Must be
+ * large enough to hold num_sectors worth of sectors.
+ *
+ * \retval 0 num_sectors were read from file
+ * \retval >0 < num_sectors were read from file
+ */
+int mvhd_fixed_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff);
+
+/**
+ * \brief Read a sparse VHD image
+ *
+ * Sparse, or dynamic images are VHD images that grow as data is written to them.
+ *
+ * This function implements the logic to read sectors from the file, taking into
+ * account the fact that blocks may be stored on disk in any order, and that the
+ * read could cross block boundaries.
+ *
+ * \param [in] vhdm MiniVHD data structure
+ * \param [in] offset Sector offset to read from
+ * \param [in] num_sectors The desired number of sectors to read
+ * \param [out] out_buff An output buffer to store read sectors. Must be
+ * large enough to hold num_sectors worth of sectors.
+ *
+ * \retval 0 num_sectors were read from file
+ * \retval >0 < num_sectors were read from file
+ */
+int mvhd_sparse_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff);
+
+/**
+ * \brief Read a differencing VHD image
+ *
+ * Differencing images are a variant of a sparse image. They contain the grow-on-demand
+ * properties of sparse images, but also reference a parent image. Data is read from the
+ * child image only if it is newer than the data stored in the parent image.
+ *
+ * This function implements the logic to read sectors from the child, or a parent image.
+ * Differencing images may have a differencing image as a parent, creating a chain of images.
+ * There is no theoretical chain length limit, although I do not consider long chains to be
+ * advisable. Verifying the parent-child relationship is not very robust.
+ *
+ * \param [in] vhdm MiniVHD data structure
+ * \param [in] offset Sector offset to read from
+ * \param [in] num_sectors The desired number of sectors to read
+ * \param [out] out_buff An output buffer to store read sectors. Must be
+ * large enough to hold num_sectors worth of sectors.
+ *
+ * \retval 0 num_sectors were read from file
+ * \retval >0 < num_sectors were read from file
+ */
+int mvhd_diff_read(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff);
+
+/**
+ * \brief Write to a fixed VHD image
+ *
+ * Fixed VHD images are essentially raw image files with a footer tacked on
+ * the end. They are therefore straightforward to write
+ *
+ * \param [in] vhdm MiniVHD data structure
+ * \param [in] offset Sector offset to write to
+ * \param [in] num_sectors The desired number of sectors to write
+ * \param [in] in_buff A source buffer to write sectors from. Must be
+ * large enough to hold num_sectors worth of sectors.
+ *
+ * \retval 0 num_sectors were written to file
+ * \retval >0 < num_sectors were written to file
+ */
+int mvhd_fixed_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff);
+
+/**
+ * \brief Write to a sparse or differencing VHD image
+ *
+ * Sparse, or dynamic images are VHD images that grow as data is written to them.
+ *
+ * Differencing images are a variant of a sparse image. They contain the grow-on-demand
+ * properties of sparse images, but also reference a parent image. Data is always written
+ * to the child image. This makes writing to differencing images essentially identical to
+ * writing to sparse images, hence they use the same function.
+ *
+ * This function implements the logic to write sectors to the file, taking into
+ * account the fact that blocks may be stored on disk in any order, and that the
+ * write operation could cross block boundaries.
+ *
+ * \param [in] vhdm MiniVHD data structure
+ * \param [in] offset Sector offset to write to
+ * \param [in] num_sectors The desired number of sectors to write
+ * \param [in] in_buff A source buffer to write sectors from. Must be
+ * large enough to hold num_sectors worth of sectors.
+ *
+ * \retval 0 num_sectors were written to file
+ * \retval >0 < num_sectors were written to file
+ */
+int mvhd_sparse_diff_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff);
+
+/**
+ * \brief A no-op function to "write" to read-only VHD images
+ *
+ * \param [in] vhdm MiniVHD data structure
+ * \param [in] offset Sector offset to write to
+ * \param [in] num_sectors The desired number of sectors to write
+ * \param [in] in_buff A source buffer to write sectors from. Must be
+ * large enough to hold num_sectors worth of sectors.
+ *
+ * \retval 0 num_sectors were written to file
+ * \retval >0 < num_sectors were written to file
+ */
+int mvhd_noop_write(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff);
+
+#endif
diff --git a/src/minivhd/minivhd_manage.c b/src/minivhd/minivhd_manage.c
new file mode 100644
index 0000000..d852a94
--- /dev/null
+++ b/src/minivhd/minivhd_manage.c
@@ -0,0 +1,538 @@
+/**
+ * \file
+ * \brief VHD management functions (open, close, read write etc)
+ */
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+#include
+#include
+#include
+#include
+#include
+#include "cwalk.h"
+#include "libxml2_encoding.h"
+#include "minivhd_internal.h"
+#include "minivhd_io.h"
+#include "minivhd_util.h"
+#include "minivhd_struct_rw.h"
+#include "minivhd.h"
+
+int mvhd_errno = 0;
+static char tmp_open_path[MVHD_MAX_PATH_BYTES] = {0};
+struct MVHDPaths {
+ char dir_path[MVHD_MAX_PATH_BYTES];
+ char file_name[MVHD_MAX_PATH_BYTES];
+ char w2ku_path[MVHD_MAX_PATH_BYTES];
+ char w2ru_path[MVHD_MAX_PATH_BYTES];
+ char joined_path[MVHD_MAX_PATH_BYTES];
+ uint16_t tmp_src_path[MVHD_MAX_PATH_CHARS];
+};
+
+static void mvhd_read_footer(MVHDMeta* vhdm);
+static void mvhd_read_sparse_header(MVHDMeta* vhdm);
+static bool mvhd_footer_checksum_valid(MVHDMeta* vhdm);
+static bool mvhd_sparse_checksum_valid(MVHDMeta* vhdm);
+static int mvhd_read_bat(MVHDMeta *vhdm, MVHDError* err);
+static void mvhd_calc_sparse_values(MVHDMeta* vhdm);
+static int mvhd_init_sector_bitmap(MVHDMeta* vhdm, MVHDError* err);
+
+/**
+ * \brief Populate data stuctures with content from a VHD footer
+ *
+ * \param [in] vhdm MiniVHD data structure
+ */
+static void mvhd_read_footer(MVHDMeta* vhdm) {
+ uint8_t buffer[MVHD_FOOTER_SIZE];
+ mvhd_fseeko64(vhdm->f, -MVHD_FOOTER_SIZE, SEEK_END);
+ fread(buffer, sizeof buffer, 1, vhdm->f);
+ mvhd_buffer_to_footer(&vhdm->footer, buffer);
+}
+
+/**
+ * \brief Populate data stuctures with content from a VHD sparse header
+ *
+ * \param [in] vhdm MiniVHD data structure
+ */
+static void mvhd_read_sparse_header(MVHDMeta* vhdm) {
+ uint8_t buffer[MVHD_SPARSE_SIZE];
+ mvhd_fseeko64(vhdm->f, vhdm->footer.data_offset, SEEK_SET);
+ fread(buffer, sizeof buffer, 1, vhdm->f);
+ mvhd_buffer_to_header(&vhdm->sparse, buffer);
+}
+
+/**
+ * \brief Validate VHD footer checksum
+ *
+ * This works by generating a checksum from the footer, and comparing it against the stored checksum.
+ *
+ * \param [in] vhdm MiniVHD data structure
+ */
+static bool mvhd_footer_checksum_valid(MVHDMeta* vhdm) {
+ return vhdm->footer.checksum == mvhd_gen_footer_checksum(&vhdm->footer);
+}
+
+/**
+ * \brief Validate VHD sparse header checksum
+ *
+ * This works by generating a checksum from the sparse header, and comparing it against the stored checksum.
+ *
+ * \param [in] vhdm MiniVHD data structure
+ */
+static bool mvhd_sparse_checksum_valid(MVHDMeta* vhdm) {
+ return vhdm->sparse.checksum == mvhd_gen_sparse_checksum(&vhdm->sparse);
+}
+
+/**
+ * \brief Read BAT into MiniVHD data structure
+ *
+ * The Block Allocation Table (BAT) is the structure in a sparse and differencing VHD which stores
+ * the 4-byte sector offsets for each data block. This function allocates enough memory to contain
+ * the entire BAT, and then reads the contents of the BAT into the buffer.
+ *
+ * \param [in] vhdm MiniVHD data structure
+ * \param [out] err this is populated with MVHD_ERR_MEM if the calloc fails
+ *
+ * \retval -1 if an error occurrs. Check value of err in this case
+ * \retval 0 if the function call succeeds
+ */
+static int mvhd_read_bat(MVHDMeta *vhdm, MVHDError* err) {
+ vhdm->block_offset = calloc(vhdm->sparse.max_bat_ent, sizeof *vhdm->block_offset);
+ if (vhdm->block_offset == NULL) {
+ *err = MVHD_ERR_MEM;
+ return -1;
+ }
+ mvhd_fseeko64(vhdm->f, vhdm->sparse.bat_offset, SEEK_SET);
+ uint32_t i;
+ for (i = 0; i < vhdm->sparse.max_bat_ent; i++) {
+ fread(&vhdm->block_offset[i], sizeof *vhdm->block_offset, 1, vhdm->f);
+ vhdm->block_offset[i] = mvhd_from_be32(vhdm->block_offset[i]);
+ }
+ return 0;
+}
+
+/**
+ * \brief Perform a one-time calculation of some sparse VHD values
+ *
+ * \param [in] vhdm MiniVHD data structure
+ */
+static void mvhd_calc_sparse_values(MVHDMeta* vhdm) {
+ vhdm->sect_per_block = vhdm->sparse.block_sz / MVHD_SECTOR_SIZE;
+ int bm_bytes = vhdm->sect_per_block / 8;
+ vhdm->bitmap.sector_count = bm_bytes / MVHD_SECTOR_SIZE;
+ if (bm_bytes % MVHD_SECTOR_SIZE > 0) {
+ vhdm->bitmap.sector_count++;
+ }
+}
+
+/**
+ * \brief Allocate memory for a sector bitmap.
+ *
+ * Each data block is preceded by a sector bitmap. Each bit indicates whether the corresponding sector
+ * is considered 'clean' or 'dirty' (for sparse VHD images), or whether to read from the parent or current
+ * image (for differencing images).
+ *
+ * \param [in] vhdm MiniVHD data structure
+ * \param [out] err this is populated with MVHD_ERR_MEM if the calloc fails
+ *
+ * \retval -1 if an error occurrs. Check value of err in this case
+ * \retval 0 if the function call succeeds
+ */
+static int mvhd_init_sector_bitmap(MVHDMeta* vhdm, MVHDError* err) {
+ vhdm->bitmap.curr_bitmap = calloc(vhdm->bitmap.sector_count, MVHD_SECTOR_SIZE);
+ if (vhdm->bitmap.curr_bitmap == NULL) {
+ *err = MVHD_ERR_MEM;
+ return -1;
+ }
+ vhdm->bitmap.curr_block = -1;
+ return 0;
+}
+
+/**
+ * \brief Check if the path for a given platform code exists
+ *
+ * From the available paths, both relative and absolute, construct a full path
+ * and attempt to open a file at that path.
+ *
+ * Note, this function makes no attempt to verify that the path is the correct
+ * VHD image, or even a VHD image at all.
+ *
+ * \param [in] paths a struct containing all available paths to work with
+ * \param [in] the platform code to try and obtain a path for. Setting this to zero
+ * will try using the directory of the child image
+ *
+ * \retval true if a file is found
+ * \retval false if a file is not found
+ */
+static bool mvhd_parent_path_exists(struct MVHDPaths* paths, uint32_t plat_code) {
+ memset(paths->joined_path, 0, sizeof paths->joined_path);
+ FILE* f;
+ int cwk_ret, ferr;
+ enum cwk_path_style style = cwk_path_guess_style((const char*)paths->dir_path);
+ cwk_path_set_style(style);
+ cwk_ret = 1;
+ if (plat_code == MVHD_DIF_LOC_W2RU && *paths->w2ru_path) {
+ cwk_ret = cwk_path_join((const char*)paths->dir_path, (const char*)paths->w2ru_path, paths->joined_path, sizeof paths->joined_path);
+ } else if (plat_code == MVHD_DIF_LOC_W2KU && *paths->w2ku_path) {
+ memcpy(paths->joined_path, paths->w2ku_path, (sizeof paths->joined_path) - 1);
+ cwk_ret = 0;
+ } else if (plat_code == 0) {
+ cwk_ret = cwk_path_join((const char*)paths->dir_path, (const char*)paths->file_name, paths->joined_path, sizeof paths->joined_path);
+ }
+ if (cwk_ret > MVHD_MAX_PATH_BYTES) {
+ return false;
+ }
+ f = mvhd_fopen((const char*)paths->joined_path, "rb", &ferr);
+ if (f != NULL) {
+ /* We found a file at the requested path! */
+ memcpy(tmp_open_path, paths->joined_path, (sizeof paths->joined_path) - 1);
+ tmp_open_path[sizeof tmp_open_path - 1] = '\0';
+ fclose(f);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ * \brief attempt to obtain a file path to a file that may be a valid VHD image
+ *
+ * Differential VHD images store both a UTF-16BE file name (or path), and up to
+ * eight "parent locator" entries. Using this information, this function tries to
+ * find a parent image.
+ *
+ * This function does not verify if the path returned is a valid parent image.
+ *
+ * \param [in] vhdm current MiniVHD data structure
+ * \param [out] err any errors that may occurr. Check this if NULL is returned
+ *
+ * \return a pointer to the global string `tmp_open_path`, or NULL if a path could
+ * not be found, or some error occurred
+ */
+static char* mvhd_get_diff_parent_path(MVHDMeta* vhdm, int* err) {
+ int utf_outlen, utf_inlen, utf_ret;
+ char* par_fp = NULL;
+ /* We can't resolve relative paths if we don't have an absolute
+ path to work with */
+ if (!cwk_path_is_absolute((const char*)vhdm->filename)) {
+ *err = MVHD_ERR_PATH_REL;
+ goto end;
+ }
+ struct MVHDPaths* paths = calloc(1, sizeof *paths);
+ if (paths == NULL) {
+ *err = MVHD_ERR_MEM;
+ goto end;
+ }
+ size_t dirlen;
+ cwk_path_get_dirname((const char*)vhdm->filename, &dirlen);
+ if (dirlen >= sizeof paths->dir_path) {
+ *err = MVHD_ERR_PATH_LEN;
+ goto paths_cleanup;
+ }
+ memcpy(paths->dir_path, vhdm->filename, dirlen);
+ /* Get the filename field from the sparse header. */
+ utf_outlen = (int)sizeof paths->file_name;
+ utf_inlen = (int)sizeof vhdm->sparse.par_utf16_name;
+ utf_ret = UTF16BEToUTF8((unsigned char*)paths->file_name, &utf_outlen, (const unsigned char*)vhdm->sparse.par_utf16_name, &utf_inlen);
+ if (utf_ret < 0) {
+ mvhd_set_encoding_err(utf_ret, err);
+ goto paths_cleanup;
+ }
+ /* Now read the parent locator entries, both relative and absolute, if they exist */
+ unsigned char* loc_path;
+ int i;
+ for (i = 0; i < 8; i++) {
+ utf_outlen = MVHD_MAX_PATH_BYTES - 1;
+ if (vhdm->sparse.par_loc_entry[i].plat_code == MVHD_DIF_LOC_W2RU) {
+ loc_path = (unsigned char*)paths->w2ru_path;
+ } else if (vhdm->sparse.par_loc_entry[i].plat_code == MVHD_DIF_LOC_W2KU) {
+ loc_path = (unsigned char*)paths->w2ku_path;
+ } else {
+ continue;
+ }
+ utf_inlen = vhdm->sparse.par_loc_entry[i].plat_data_len;
+ if (utf_inlen > MVHD_MAX_PATH_BYTES) {
+ *err = MVHD_ERR_PATH_LEN;
+ goto paths_cleanup;
+ }
+ mvhd_fseeko64(vhdm->f, vhdm->sparse.par_loc_entry[i].plat_data_offset, SEEK_SET);
+ fread(paths->tmp_src_path, sizeof (uint8_t), utf_inlen, vhdm->f);
+ /* Note, the W2*u parent locators are UTF-16LE, unlike the filename field previously obtained,
+ which is UTF-16BE */
+ utf_ret = UTF16LEToUTF8(loc_path, &utf_outlen, (const unsigned char*)paths->tmp_src_path, &utf_inlen);
+ if (utf_ret < 0) {
+ mvhd_set_encoding_err(utf_ret, err);
+ goto paths_cleanup;
+ }
+ }
+ /* We have paths in UTF-8. We should have enough info to try and find the parent VHD */
+ /* Does the relative path exist? */
+ if (mvhd_parent_path_exists(paths, MVHD_DIF_LOC_W2RU)) {
+ par_fp = tmp_open_path;
+ goto paths_cleanup;
+ }
+ /* What about trying the child directory? */
+ if (mvhd_parent_path_exists(paths, 0)) {
+ par_fp = tmp_open_path;
+ goto paths_cleanup;
+ }
+ /* Well, all else fails, try the stored absolute path, if it exists */
+ if (mvhd_parent_path_exists(paths, MVHD_DIF_LOC_W2KU)) {
+ par_fp = tmp_open_path;
+ goto paths_cleanup;
+ }
+ /* If we reach this point, we could not find a path with a valid file */
+ par_fp = NULL;
+ *err = MVHD_ERR_PAR_NOT_FOUND;
+
+paths_cleanup:
+ free(paths);
+ paths = NULL;
+end:
+ return par_fp;
+}
+
+/**
+ * \brief Attach the read/write function pointers to read/write functions
+ *
+ * Depending on the VHD type, different sector reading and writing functions are used.
+ * The functions are called via function pointers stored in the vhdm struct.
+ *
+ * \param [in] vhdm MiniVHD data structure
+ */
+static void mvhd_assign_io_funcs(MVHDMeta* vhdm) {
+ switch (vhdm->footer.disk_type) {
+ case MVHD_TYPE_FIXED:
+ vhdm->read_sectors = mvhd_fixed_read;
+ vhdm->write_sectors = mvhd_fixed_write;
+ break;
+ case MVHD_TYPE_DYNAMIC:
+ vhdm->read_sectors = mvhd_sparse_read;
+ vhdm->write_sectors = mvhd_sparse_diff_write;
+ break;
+ case MVHD_TYPE_DIFF:
+ vhdm->read_sectors = mvhd_diff_read;
+ vhdm->write_sectors = mvhd_sparse_diff_write;
+ break;
+ }
+ if (vhdm->readonly) {
+ vhdm->write_sectors = mvhd_noop_write;
+ }
+}
+
+bool mvhd_file_is_vhd(FILE* f) {
+ if (f) {
+ uint8_t con_str[8];
+ mvhd_fseeko64(f, -MVHD_FOOTER_SIZE, SEEK_END);
+ fread(con_str, sizeof con_str, 1, f);
+ return mvhd_is_conectix_str(con_str);
+ } else {
+ return false;
+ }
+}
+
+MVHDGeom mvhd_calculate_geometry(uint64_t size) {
+ MVHDGeom chs;
+ uint32_t ts = (uint32_t)(size / MVHD_SECTOR_SIZE);
+ uint32_t spt, heads, cyl, cth;
+ if (ts > 65535 * 16 * 255) {
+ ts = 65535 * 16 * 255;
+ }
+ if (ts >= 65535 * 16 * 63) {
+ spt = 255;
+ heads = 16;
+ cth = ts / spt;
+ } else {
+ spt = 17;
+ cth = ts / spt;
+ heads = (cth + 1023) / 1024;
+ if (heads < 4) {
+ heads = 4;
+ }
+ if (cth >= (heads * 1024) || heads > 16) {
+ spt = 31;
+ heads = 16;
+ cth = ts / spt;
+ }
+ if (cth >= (heads * 1024)) {
+ spt = 63;
+ heads = 16;
+ cth = ts / spt;
+ }
+ }
+ cyl = cth / heads;
+ chs.heads = heads;
+ chs.spt = spt;
+ chs.cyl = cyl;
+ return chs;
+}
+
+MVHDMeta* mvhd_open(const char* path, bool readonly, int* err) {
+ MVHDError open_err;
+ MVHDMeta *vhdm = calloc(sizeof *vhdm, 1);
+ if (vhdm == NULL) {
+ *err = MVHD_ERR_MEM;
+ goto end;
+ }
+ if (strlen(path) >= sizeof vhdm->filename) {
+ *err = MVHD_ERR_PATH_LEN;
+ goto cleanup_vhdm;
+ }
+ //This is safe, as we've just checked for potential overflow above
+ strcpy(vhdm->filename, path);
+ vhdm->f = readonly ? mvhd_fopen((const char*)vhdm->filename, "rb", err) : mvhd_fopen((const char*)vhdm->filename, "rb+", err);
+ if (vhdm->f == NULL) {
+ /* note, mvhd_fopen sets err for us */
+ goto cleanup_vhdm;
+ }
+ vhdm->readonly = readonly;
+ if (!mvhd_file_is_vhd(vhdm->f)) {
+ *err = MVHD_ERR_NOT_VHD;
+ goto cleanup_file;
+ }
+ mvhd_read_footer(vhdm);
+ if (!mvhd_footer_checksum_valid(vhdm)) {
+ *err = MVHD_ERR_FOOTER_CHECKSUM;
+ goto cleanup_file;
+ }
+ if (vhdm->footer.disk_type == MVHD_TYPE_DIFF || vhdm->footer.disk_type == MVHD_TYPE_DYNAMIC) {
+ mvhd_read_sparse_header(vhdm);
+ if (!mvhd_sparse_checksum_valid(vhdm)) {
+ *err = MVHD_ERR_SPARSE_CHECKSUM;
+ goto cleanup_file;
+ }
+ if (mvhd_read_bat(vhdm, &open_err) == -1) {
+ *err = open_err;
+ goto cleanup_file;
+ }
+ mvhd_calc_sparse_values(vhdm);
+ if (mvhd_init_sector_bitmap(vhdm, &open_err) == -1) {
+ *err = open_err;
+ goto cleanup_bat;
+ }
+
+ } else if (vhdm->footer.disk_type != MVHD_TYPE_FIXED) {
+ *err = MVHD_ERR_TYPE;
+ goto cleanup_bitmap;
+ }
+ mvhd_assign_io_funcs(vhdm);
+ vhdm->format_buffer.zero_data = calloc(64, MVHD_SECTOR_SIZE);
+ if (vhdm->format_buffer.zero_data == NULL) {
+ *err = MVHD_ERR_MEM;
+ goto cleanup_bitmap;
+ }
+ vhdm->format_buffer.sector_count = 64;
+ if (vhdm->footer.disk_type == MVHD_TYPE_DIFF) {
+ char* par_path = mvhd_get_diff_parent_path(vhdm, err);
+ if (par_path == NULL) {
+ goto cleanup_format_buff;
+ }
+ uint32_t par_mod_ts = mvhd_file_mod_timestamp(par_path, err);
+ if (*err != 0) {
+ goto cleanup_format_buff;
+ }
+ if (vhdm->sparse.par_timestamp != par_mod_ts) {
+ /* The last-modified timestamp is to fragile to make this a fatal error.
+ Instead, we inform the caller of the potential problem. */
+ *err = MVHD_ERR_TIMESTAMP;
+ }
+ vhdm->parent = mvhd_open(par_path, true, err);
+ if (vhdm->parent == NULL) {
+ goto cleanup_format_buff;
+ }
+ if (memcmp(vhdm->sparse.par_uuid, vhdm->parent->footer.uuid, sizeof vhdm->sparse.par_uuid) != 0) {
+ *err = MVHD_ERR_INVALID_PAR_UUID;
+ goto cleanup_format_buff;
+ }
+ }
+ /* If we've reached this point, we are good to go, so skip the cleanup steps */
+ goto end;
+cleanup_format_buff:
+ free(vhdm->format_buffer.zero_data);
+ vhdm->format_buffer.zero_data = NULL;
+cleanup_bitmap:
+ free(vhdm->bitmap.curr_bitmap);
+ vhdm->bitmap.curr_bitmap = NULL;
+cleanup_bat:
+ free(vhdm->block_offset);
+ vhdm->block_offset = NULL;
+cleanup_file:
+ fclose(vhdm->f);
+ vhdm->f = NULL;
+cleanup_vhdm:
+ free(vhdm);
+ vhdm = NULL;
+end:
+ return vhdm;
+}
+
+void mvhd_close(MVHDMeta* vhdm) {
+ if (vhdm != NULL) {
+ if (vhdm->parent != NULL) {
+ mvhd_close(vhdm->parent);
+ }
+ fclose(vhdm->f);
+ if (vhdm->block_offset != NULL) {
+ free(vhdm->block_offset);
+ vhdm->block_offset = NULL;
+ }
+ if (vhdm->bitmap.curr_bitmap != NULL) {
+ free(vhdm->bitmap.curr_bitmap);
+ vhdm->bitmap.curr_bitmap = NULL;
+ }
+ if (vhdm->format_buffer.zero_data != NULL) {
+ free(vhdm->format_buffer.zero_data);
+ vhdm->format_buffer.zero_data = NULL;
+ }
+ free(vhdm);
+ vhdm = NULL;
+ }
+}
+
+int mvhd_diff_update_par_timestamp(MVHDMeta* vhdm, int* err) {
+ uint8_t sparse_buff[1024];
+ if (vhdm == NULL || err == NULL) {
+ *err = MVHD_ERR_INVALID_PARAMS;
+ return -1;
+ }
+ if (vhdm->footer.disk_type != MVHD_TYPE_DIFF) {
+ *err = MVHD_ERR_TYPE;
+ return -1;
+ }
+ char* par_path = mvhd_get_diff_parent_path(vhdm, err);
+ if (par_path == NULL) {
+ return -1;
+ }
+ uint32_t par_mod_ts = mvhd_file_mod_timestamp(par_path, err);
+ if (*err != 0) {
+ return -1;
+ }
+ /* Update the timestamp and sparse header checksum */
+ vhdm->sparse.par_timestamp = par_mod_ts;
+ vhdm->sparse.checksum = mvhd_gen_sparse_checksum(&vhdm->sparse);
+ /* Generate and write the updated sparse header */
+ mvhd_header_to_buffer(&vhdm->sparse, sparse_buff);
+ mvhd_fseeko64(vhdm->f, (int64_t)vhdm->footer.data_offset, SEEK_SET);
+ fwrite(sparse_buff, sizeof sparse_buff, 1, vhdm->f);
+ return 0;
+}
+
+int mvhd_read_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* out_buff) {
+ return vhdm->read_sectors(vhdm, offset, num_sectors, out_buff);
+}
+
+int mvhd_write_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors, void* in_buff) {
+ return vhdm->write_sectors(vhdm, offset, num_sectors, in_buff);
+}
+
+int mvhd_format_sectors(MVHDMeta* vhdm, uint32_t offset, int num_sectors) {
+ int num_full = num_sectors / vhdm->format_buffer.sector_count;
+ int remain = num_sectors % vhdm->format_buffer.sector_count;
+ int i;
+ for (i = 0; i < num_full; i++) {
+ vhdm->write_sectors(vhdm, offset, vhdm->format_buffer.sector_count, vhdm->format_buffer.zero_data);
+ offset += vhdm->format_buffer.sector_count;
+ }
+ vhdm->write_sectors(vhdm, offset, remain, vhdm->format_buffer.zero_data);
+ return 0;
+}
diff --git a/src/minivhd/minivhd_struct_rw.c b/src/minivhd/minivhd_struct_rw.c
new file mode 100644
index 0000000..77f26a4
--- /dev/null
+++ b/src/minivhd/minivhd_struct_rw.c
@@ -0,0 +1,169 @@
+/**
+ * \file
+ * \brief Header and footer serialize/deserialize functions
+ */
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+#include
+#include
+#include
+#include
+#include
+#include "minivhd_util.h"
+#include "minivhd_internal.h"
+
+/* Read data from footer into the struct members, swapping endian where necessary
+ Note: order matters here! We must read each field in the order the struct is in.
+ Doing this may be less elegant than performing a memcpy to a packed struct, but
+ it avoids potential data alignment issues, and the endian swapping allows us to
+ use the fields directly. */
+
+static void mvhd_next_buffer_to_struct(void* struct_memb, size_t memb_size, bool req_endian, uint8_t** buffer);
+static void mvhd_next_struct_to_buffer(void* struct_memb, size_t memb_size, bool req_endian, uint8_t** buffer);
+
+/**
+ * \brief Get the next field from a buffer and store it in a struct member, converting endian if necessary
+ *
+ * \param [out] struct_memb struct member to save the field to
+ * \param [in] memb_size the size of struct_memb, in bytes
+ * \param [in] req_endian is the field a value that requires endian conversion (eg: uint16, uint32)
+ * \param [in] buffer the buffer from which fields are read from. Will be advanced at the end of the function call
+ */
+static void mvhd_next_buffer_to_struct(void* struct_memb, size_t memb_size, bool req_endian, uint8_t** buffer) {
+ memcpy(struct_memb, *buffer, memb_size);
+ if (req_endian) {
+ switch (memb_size) {
+ case 2:
+ *(uint16_t*)(struct_memb) = mvhd_from_be16(*(uint16_t*)(struct_memb));
+ break;
+ case 4:
+ *(uint32_t*)(struct_memb) = mvhd_from_be32(*(uint32_t*)(struct_memb));
+ break;
+ case 8:
+ *(uint64_t*)(struct_memb) = mvhd_from_be64(*(uint64_t*)(struct_memb));
+ break;
+ }
+ }
+ *buffer += memb_size;
+}
+
+/**
+ * \brief Save a struct member into a buffer, converting endian if necessary
+ *
+ * \param [in] struct_memb struct member read from
+ * \param [in] memb_size the size of struct_memb, in bytes
+ * \param [in] req_endian is the field a value that requires endian conversion (eg: uint16, uint32)
+ * \param [out] buffer the buffer from which struct member is saved to. Will be advanced at the end of the function call
+ */
+static void mvhd_next_struct_to_buffer(void* struct_memb, size_t memb_size, bool req_endian, uint8_t** buffer) {
+ uint8_t *buf_ptr = *buffer;
+ memcpy(buf_ptr, struct_memb, memb_size);
+ if (req_endian) {
+ switch (memb_size) {
+ case 2:
+ *((uint16_t*)buf_ptr) = mvhd_to_be16(*(uint16_t*)(struct_memb));
+ break;
+ case 4:
+ *((uint32_t*)buf_ptr) = mvhd_to_be32(*(uint32_t*)(struct_memb));
+ break;
+ case 8:
+ *((uint64_t*)buf_ptr) = mvhd_to_be64(*(uint64_t*)(struct_memb));
+ break;
+ }
+ }
+ buf_ptr += memb_size;
+ *buffer = buf_ptr;
+}
+
+void mvhd_buffer_to_footer(MVHDFooter* footer, uint8_t* buffer) {
+ uint8_t* buff_ptr = buffer;
+ mvhd_next_buffer_to_struct(&footer->cookie, sizeof footer->cookie, false, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->features, sizeof footer->features, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->fi_fmt_vers, sizeof footer->fi_fmt_vers, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->data_offset, sizeof footer->data_offset, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->timestamp, sizeof footer->timestamp, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->cr_app, sizeof footer->cr_app, false, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->cr_vers, sizeof footer->cr_vers, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->cr_host_os, sizeof footer->cr_host_os, false, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->orig_sz, sizeof footer->orig_sz, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->curr_sz, sizeof footer->curr_sz, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->geom.cyl, sizeof footer->geom.cyl, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->geom.heads, sizeof footer->geom.heads, false, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->geom.spt, sizeof footer->geom.spt, false, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->disk_type, sizeof footer->disk_type, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->checksum, sizeof footer->checksum, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->uuid, sizeof footer->uuid, false, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->saved_st, sizeof footer->saved_st, false, &buff_ptr);
+ mvhd_next_buffer_to_struct(&footer->reserved, sizeof footer->reserved, false, &buff_ptr);
+}
+
+void mvhd_footer_to_buffer(MVHDFooter* footer, uint8_t* buffer) {
+ uint8_t* buff_ptr = buffer;
+ mvhd_next_struct_to_buffer(&footer->cookie, sizeof footer->cookie, false, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->features, sizeof footer->features, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->fi_fmt_vers, sizeof footer->fi_fmt_vers, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->data_offset, sizeof footer->data_offset, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->timestamp, sizeof footer->timestamp, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->cr_app, sizeof footer->cr_app, false, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->cr_vers, sizeof footer->cr_vers, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->cr_host_os, sizeof footer->cr_host_os, false, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->orig_sz, sizeof footer->orig_sz, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->curr_sz, sizeof footer->curr_sz, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->geom.cyl, sizeof footer->geom.cyl, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->geom.heads, sizeof footer->geom.heads, false, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->geom.spt, sizeof footer->geom.spt, false, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->disk_type, sizeof footer->disk_type, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->checksum, sizeof footer->checksum, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->uuid, sizeof footer->uuid, false, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->saved_st, sizeof footer->saved_st, false, &buff_ptr);
+ mvhd_next_struct_to_buffer(&footer->reserved, sizeof footer->reserved, false, &buff_ptr);
+}
+
+void mvhd_buffer_to_header(MVHDSparseHeader* header, uint8_t* buffer) {
+ uint8_t* buff_ptr = buffer;
+ mvhd_next_buffer_to_struct(&header->cookie, sizeof header->cookie, false, &buff_ptr);
+ mvhd_next_buffer_to_struct(&header->data_offset, sizeof header->data_offset, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&header->bat_offset, sizeof header->bat_offset, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&header->head_vers, sizeof header->head_vers, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&header->max_bat_ent, sizeof header->max_bat_ent, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&header->block_sz, sizeof header->block_sz, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&header->checksum, sizeof header->checksum, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&header->par_uuid, sizeof header->par_uuid, false, &buff_ptr);
+ mvhd_next_buffer_to_struct(&header->par_timestamp, sizeof header->par_timestamp, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&header->reserved_1, sizeof header->reserved_1, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&header->par_utf16_name, sizeof header->par_utf16_name, false, &buff_ptr);
+ int i;
+ for (i = 0; i < 8; i++) {
+ mvhd_next_buffer_to_struct(&header->par_loc_entry[i].plat_code, sizeof header->par_loc_entry[i].plat_code, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&header->par_loc_entry[i].plat_data_space, sizeof header->par_loc_entry[i].plat_data_space, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&header->par_loc_entry[i].plat_data_len, sizeof header->par_loc_entry[i].plat_data_len, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&header->par_loc_entry[i].reserved, sizeof header->par_loc_entry[i].reserved, true, &buff_ptr);
+ mvhd_next_buffer_to_struct(&header->par_loc_entry[i].plat_data_offset, sizeof header->par_loc_entry[i].plat_data_offset, true, &buff_ptr);
+ }
+ mvhd_next_buffer_to_struct(&header->reserved_2, sizeof header->reserved_2, false, &buff_ptr);
+}
+
+void mvhd_header_to_buffer(MVHDSparseHeader* header, uint8_t* buffer) {
+ uint8_t* buff_ptr = buffer;
+ mvhd_next_struct_to_buffer(&header->cookie, sizeof header->cookie, false, &buff_ptr);
+ mvhd_next_struct_to_buffer(&header->data_offset, sizeof header->data_offset, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&header->bat_offset, sizeof header->bat_offset, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&header->head_vers, sizeof header->head_vers, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&header->max_bat_ent, sizeof header->max_bat_ent, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&header->block_sz, sizeof header->block_sz, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&header->checksum, sizeof header->checksum, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&header->par_uuid, sizeof header->par_uuid, false, &buff_ptr);
+ mvhd_next_struct_to_buffer(&header->par_timestamp, sizeof header->par_timestamp, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&header->reserved_1, sizeof header->reserved_1, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&header->par_utf16_name, sizeof header->par_utf16_name, false, &buff_ptr);
+ int i;
+ for (i = 0; i < 8; i++) {
+ mvhd_next_struct_to_buffer(&header->par_loc_entry[i].plat_code, sizeof header->par_loc_entry[i].plat_code, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&header->par_loc_entry[i].plat_data_space, sizeof header->par_loc_entry[i].plat_data_space, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&header->par_loc_entry[i].plat_data_len, sizeof header->par_loc_entry[i].plat_data_len, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&header->par_loc_entry[i].reserved, sizeof header->par_loc_entry[i].reserved, true, &buff_ptr);
+ mvhd_next_struct_to_buffer(&header->par_loc_entry[i].plat_data_offset, sizeof header->par_loc_entry[i].plat_data_offset, true, &buff_ptr);
+ }
+ mvhd_next_struct_to_buffer(&header->reserved_2, sizeof header->reserved_2, false, &buff_ptr);
+}
diff --git a/src/minivhd/minivhd_struct_rw.h b/src/minivhd/minivhd_struct_rw.h
new file mode 100644
index 0000000..a587177
--- /dev/null
+++ b/src/minivhd/minivhd_struct_rw.h
@@ -0,0 +1,38 @@
+#ifndef MINIVHD_STRUCT_RW_H
+#define MINIVHD_STRUCT_RW_H
+
+#include "minivhd_internal.h"
+
+/**
+ * \brief Save the contents of a VHD footer from a buffer to a struct
+ *
+ * \param [out] footer save contents of buffer into footer
+ * \param [in] buffer VHD footer in raw bytes
+ */
+void mvhd_buffer_to_footer(MVHDFooter* footer, uint8_t* buffer);
+
+/**
+ * \brief Save the contents of a VHD sparse header from a buffer to a struct
+ *
+ * \param [out] header save contents of buffer into header
+ * \param [in] buffer VHD header in raw bytes
+ */
+void mvhd_buffer_to_header(MVHDSparseHeader* header, uint8_t* buffer);
+
+/**
+ * \brief Save the contents of a VHD footer struct to a buffer
+ *
+ * \param [in] footer save contents of struct into buffer
+ * \param [out] buffer VHD footer in raw bytes
+ */
+void mvhd_footer_to_buffer(MVHDFooter* footer, uint8_t* buffer);
+
+/**
+ * \brief Save the contents of a VHD sparse header struct to a buffer
+ *
+ * \param [in] header save contents of struct into buffer
+ * \param [out] buffer VHD sparse header in raw bytes
+ */
+void mvhd_header_to_buffer(MVHDSparseHeader* header, uint8_t* buffer);
+
+#endif
diff --git a/src/minivhd/minivhd_util.c b/src/minivhd/minivhd_util.c
new file mode 100644
index 0000000..b04e022
--- /dev/null
+++ b/src/minivhd/minivhd_util.c
@@ -0,0 +1,339 @@
+/**
+ * \file
+ * \brief Utility functions
+ */
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "libxml2_encoding.h"
+#include "minivhd_internal.h"
+#include "minivhd_util.h"
+#include "minivhd.h"
+
+const char MVHD_CONECTIX_COOKIE[] = "conectix";
+const char MVHD_CREATOR[] = "pcem";
+const char MVHD_CREATOR_HOST_OS[] = "Wi2k";
+const char MVHD_CXSPARSE_COOKIE[] = "cxsparse";
+
+uint16_t mvhd_from_be16(uint16_t val) {
+ uint8_t *tmp = (uint8_t*)&val;
+ uint16_t ret = 0;
+ ret |= (uint16_t)tmp[0] << 8;
+ ret |= (uint16_t)tmp[1] << 0;
+ return ret;
+}
+uint32_t mvhd_from_be32(uint32_t val) {
+ uint8_t *tmp = (uint8_t*)&val;
+ uint32_t ret = 0;
+ ret = (uint32_t)tmp[0] << 24;
+ ret |= (uint32_t)tmp[1] << 16;
+ ret |= (uint32_t)tmp[2] << 8;
+ ret |= (uint32_t)tmp[3] << 0;
+ return ret;
+}
+uint64_t mvhd_from_be64(uint64_t val) {
+ uint8_t *tmp = (uint8_t*)&val;
+ uint64_t ret = 0;
+ ret = (uint64_t)tmp[0] << 56;
+ ret |= (uint64_t)tmp[1] << 48;
+ ret |= (uint64_t)tmp[2] << 40;
+ ret |= (uint64_t)tmp[3] << 32;
+ ret |= (uint64_t)tmp[4] << 24;
+ ret |= (uint64_t)tmp[5] << 16;
+ ret |= (uint64_t)tmp[6] << 8;
+ ret |= (uint64_t)tmp[7] << 0;
+ return ret;
+}
+uint16_t mvhd_to_be16(uint16_t val) {
+ uint16_t ret = 0;
+ uint8_t *tmp = (uint8_t*)&ret;
+ tmp[0] = (val & 0xff00) >> 8;
+ tmp[1] = (val & 0x00ff) >> 0;
+ return ret;
+}
+uint32_t mvhd_to_be32(uint32_t val) {
+ uint32_t ret = 0;
+ uint8_t *tmp = (uint8_t*)&ret;
+ tmp[0] = (val & 0xff000000) >> 24;
+ tmp[1] = (val & 0x00ff0000) >> 16;
+ tmp[2] = (val & 0x0000ff00) >> 8;
+ tmp[3] = (val & 0x000000ff) >> 0;
+ return ret;
+}
+uint64_t mvhd_to_be64(uint64_t val) {
+ uint64_t ret = 0;
+ uint8_t *tmp = (uint8_t*)&ret;
+ tmp[0] = (uint8_t)((val & 0xff00000000000000) >> 56);
+ tmp[1] = (uint8_t)((val & 0x00ff000000000000) >> 48);
+ tmp[2] = (uint8_t)((val & 0x0000ff0000000000) >> 40);
+ tmp[3] = (uint8_t)((val & 0x000000ff00000000) >> 32);
+ tmp[4] = (uint8_t)((val & 0x00000000ff000000) >> 24);
+ tmp[5] = (uint8_t)((val & 0x0000000000ff0000) >> 16);
+ tmp[6] = (uint8_t)((val & 0x000000000000ff00) >> 8);
+ tmp[7] = (uint8_t)((val & 0x00000000000000ff) >> 0);
+ return ret;
+}
+
+bool mvhd_is_conectix_str(const void* buffer) {
+ if (strncmp(buffer, MVHD_CONECTIX_COOKIE, strlen(MVHD_CONECTIX_COOKIE)) == 0) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void mvhd_generate_uuid(uint8_t* uuid)
+{
+ /* We aren't doing crypto here, so using system time as seed should be good enough */
+ srand((unsigned int)time(0));
+ int n;
+ for (n = 0; n < 16; n++) {
+ uuid[n] = rand();
+ }
+ uuid[6] &= 0x0F;
+ uuid[6] |= 0x40; /* Type 4 */
+ uuid[8] &= 0x3F;
+ uuid[8] |= 0x80; /* Variant 1 */
+}
+
+uint32_t vhd_calc_timestamp(void)
+{
+ time_t start_time;
+ time_t curr_time;
+ double vhd_time;
+ start_time = MVHD_START_TS; /* 1 Jan 2000 00:00 */
+ curr_time = time(NULL);
+ vhd_time = difftime(curr_time, start_time);
+ return (uint32_t)vhd_time;
+}
+
+uint32_t mvhd_epoch_to_vhd_ts(time_t ts) {
+ time_t start_time = MVHD_START_TS;
+ if (ts < start_time) {
+ return start_time;
+ }
+ double vhd_time = difftime(ts, start_time);
+ return (uint32_t)vhd_time;
+}
+
+time_t vhd_get_created_time(MVHDMeta *vhdm)
+{
+ time_t vhd_time = (time_t)vhdm->footer.timestamp;
+ time_t vhd_time_unix = MVHD_START_TS + vhd_time;
+ return vhd_time_unix;
+}
+
+FILE* mvhd_fopen(const char* path, const char* mode, int* err) {
+ FILE* f = NULL;
+#ifdef _WIN32
+ size_t path_len = strlen(path);
+ size_t mode_len = strlen(mode);
+ mvhd_utf16 new_path[260] = {0};
+ int new_path_len = (sizeof new_path) - 2;
+ mvhd_utf16 mode_str[5] = {0};
+ int new_mode_len = (sizeof mode_str) - 2;
+ int path_res = UTF8ToUTF16LE((unsigned char*)new_path, &new_path_len, (const unsigned char*)path, (int*)&path_len);
+ int mode_res = UTF8ToUTF16LE((unsigned char*)mode_str, &new_mode_len, (const unsigned char*)mode, (int*)&mode_len);
+ if (path_res > 0 && mode_res > 0) {
+ f = _wfopen(new_path, mode_str);
+ if (f == NULL) {
+ mvhd_errno = errno;
+ *err = MVHD_ERR_FILE;
+ }
+ } else {
+ if (path_res == -1 || mode_res == -1) {
+ *err = MVHD_ERR_UTF_SIZE;
+ } else if (path_res == -2 || mode_res == -2) {
+ *err = MVHD_ERR_UTF_TRANSCODING_FAILED;
+ }
+ }
+#else
+ f = fopen(path, mode);
+ if (f == NULL) {
+ mvhd_errno = errno;
+ *err = MVHD_ERR_FILE;
+ }
+#endif
+ return f;
+}
+
+void mvhd_set_encoding_err(int encoding_retval, int* err) {
+ if (encoding_retval == -1) {
+ *err = MVHD_ERR_UTF_SIZE;
+ } else if (encoding_retval == -2) {
+ *err = MVHD_ERR_UTF_TRANSCODING_FAILED;
+ }
+}
+
+uint64_t mvhd_calc_size_bytes(MVHDGeom *geom) {
+ uint64_t img_size = (uint64_t)geom->cyl * (uint64_t)geom->heads * (uint64_t)geom->spt * (uint64_t)MVHD_SECTOR_SIZE;
+ return img_size;
+}
+
+uint32_t mvhd_calc_size_sectors(MVHDGeom *geom) {
+ uint32_t sector_size = (uint32_t)geom->cyl * (uint32_t)geom->heads * (uint32_t)geom->spt;
+ return sector_size;
+}
+
+MVHDGeom mvhd_get_geometry(MVHDMeta* vhdm) {
+ MVHDGeom geometry = { .cyl = vhdm->footer.geom.cyl, .heads = vhdm->footer.geom.heads, .spt = vhdm->footer.geom.spt };
+ return geometry;
+}
+
+uint64_t mvhd_get_current_size(MVHDMeta* vhdm) {
+ return vhdm->footer.curr_sz;
+}
+
+uint32_t mvhd_gen_footer_checksum(MVHDFooter* footer) {
+ uint32_t new_chk = 0;
+ uint32_t orig_chk = footer->checksum;
+ footer->checksum = 0;
+ uint8_t* footer_bytes = (uint8_t*)footer;
+ size_t i;
+ for (i = 0; i < sizeof *footer; i++) {
+ new_chk += footer_bytes[i];
+ }
+ footer->checksum = orig_chk;
+ return ~new_chk;
+}
+
+uint32_t mvhd_gen_sparse_checksum(MVHDSparseHeader* header) {
+ uint32_t new_chk = 0;
+ uint32_t orig_chk = header->checksum;
+ header->checksum = 0;
+ uint8_t* sparse_bytes = (uint8_t*)header;
+ size_t i;
+ for (i = 0; i < sizeof *header; i++) {
+ new_chk += sparse_bytes[i];
+ }
+ header->checksum = orig_chk;
+ return ~new_chk;
+}
+
+const char* mvhd_strerr(MVHDError err) {
+ switch (err) {
+ case MVHD_ERR_MEM:
+ return "memory allocation error";
+ case MVHD_ERR_FILE:
+ return "file error";
+ case MVHD_ERR_NOT_VHD:
+ return "file is not a VHD image";
+ case MVHD_ERR_TYPE:
+ return "unsupported VHD image type";
+ case MVHD_ERR_FOOTER_CHECKSUM:
+ return "invalid VHD footer checksum";
+ case MVHD_ERR_SPARSE_CHECKSUM:
+ return "invalid VHD sparse header checksum";
+ case MVHD_ERR_UTF_TRANSCODING_FAILED:
+ return "error converting path encoding";
+ case MVHD_ERR_UTF_SIZE:
+ return "buffer size mismatch when converting path encoding";
+ case MVHD_ERR_PATH_REL:
+ return "relative path detected where absolute path expected";
+ case MVHD_ERR_PATH_LEN:
+ return "path length exceeds MVHD_MAX_PATH";
+ case MVHD_ERR_PAR_NOT_FOUND:
+ return "parent VHD image not found";
+ case MVHD_ERR_INVALID_PAR_UUID:
+ return "UUID mismatch between child and parent VHD";
+ case MVHD_ERR_INVALID_GEOM:
+ return "invalid geometry detected";
+ case MVHD_ERR_INVALID_SIZE:
+ return "invalid size";
+ case MVHD_ERR_INVALID_BLOCK_SIZE:
+ return "invalid block size";
+ case MVHD_ERR_INVALID_PARAMS:
+ return "invalid parameters passed to function";
+ case MVHD_ERR_CONV_SIZE:
+ return "error converting image. Size mismatch detechted";
+ default:
+ return "unknown error";
+ }
+}
+
+int64_t mvhd_ftello64(FILE* stream)
+{
+#ifdef _MSC_VER
+ return _ftelli64(stream);
+#elif defined(__MINGW32__)
+ return ftello64(stream);
+#else /* This should work with linux (with _FILE_OFFSET_BITS), and hopefully OS X and BSD */
+ return ftello(stream);
+#endif
+}
+
+int mvhd_fseeko64(FILE* stream, int64_t offset, int origin)
+{
+#ifdef _MSC_VER
+ return _fseeki64(stream, offset, origin);
+#elif defined(__MINGW32__)
+ return fseeko64(stream, offset, origin);
+#else /* This should work with linux (with _FILE_OFFSET_BITS), and hopefully OS X and BSD */
+ return fseeko(stream, offset, origin);
+#endif
+}
+
+uint32_t mvhd_crc32_for_byte(uint32_t r) {
+ int j;
+ for (j = 0; j < 8; ++j)
+ r = (r & 1 ? 0 : (uint32_t)0xEDB88320L) ^ r >> 1;
+ return r ^ (uint32_t)0xFF000000L;
+}
+
+uint32_t mvhd_crc32(const void* data, size_t n_bytes) {
+ static uint32_t table[0x100];
+ size_t i;
+ if (!*table)
+ for (i = 0; i < 0x100; ++i)
+ table[i] = mvhd_crc32_for_byte(i);
+
+ uint32_t crc = 0;
+ for (i = 0; i < n_bytes; ++i)
+ crc = table[(uint8_t)crc ^ ((uint8_t*)data)[i]] ^ crc >> 8;
+
+ return crc;
+}
+
+uint32_t mvhd_file_mod_timestamp(const char* path, int *err) {
+ *err = 0;
+#ifdef _WIN32
+ struct _stat file_stat;
+ size_t path_len = strlen(path);
+ mvhd_utf16 new_path[260] = {0};
+ int new_path_len = (sizeof new_path) - 2;
+ int path_res = UTF8ToUTF16LE((unsigned char*)new_path, &new_path_len, (const unsigned char*)path, (int*)&path_len);
+ if (path_res > 0) {
+ int stat_res = _wstat(new_path, &file_stat);
+ if (stat_res != 0) {
+ mvhd_errno = errno;
+ *err = MVHD_ERR_FILE;
+ return 0;
+ }
+ return mvhd_epoch_to_vhd_ts(file_stat.st_mtime);
+ } else {
+ if (path_res == -1) {
+ *err = MVHD_ERR_UTF_SIZE;
+ } else if (path_res == -2) {
+ *err = MVHD_ERR_UTF_TRANSCODING_FAILED;
+ }
+ return 0;
+ }
+#else
+ struct stat file_stat;
+ int stat_res = stat(path, &file_stat);
+ if (stat_res != 0) {
+ mvhd_errno = errno;
+ *err = MVHD_ERR_FILE;
+ return 0;
+ }
+ return mvhd_epoch_to_vhd_ts(file_stat.st_mtime);
+#endif
+}
diff --git a/src/minivhd/minivhd_util.h b/src/minivhd/minivhd_util.h
new file mode 100644
index 0000000..8a18b55
--- /dev/null
+++ b/src/minivhd/minivhd_util.h
@@ -0,0 +1,133 @@
+#ifndef MINIVHD_UTIL_H
+#define MINIVHD_UTIL_H
+
+#include
+#include
+#include
+#include "minivhd_internal.h"
+#include "minivhd.h"
+#define MVHD_START_TS 946684800
+
+/**
+ * Functions to deal with endian issues
+ */
+uint16_t mvhd_from_be16(uint16_t val);
+uint32_t mvhd_from_be32(uint32_t val);
+uint64_t mvhd_from_be64(uint64_t val);
+uint16_t mvhd_to_be16(uint16_t val);
+uint32_t mvhd_to_be32(uint32_t val);
+uint64_t mvhd_to_be64(uint64_t val);
+
+/**
+ * \brief Check if provided buffer begins with the string "conectix"
+ *
+ * \param [in] buffer The buffer to compare. Must be at least 8 bytes in length
+ *
+ * \return true if the buffer begins with "conectix"
+ * \return false if the buffer does not begin with "conectix"
+ */
+bool mvhd_is_conectix_str(const void* buffer);
+
+/**
+ * \brief Generate a raw 16 byte UUID
+ *
+ * \param [out] uuid A 16 byte buffer in which the generated UUID will be stored to
+ */
+void mvhd_generate_uuid(uint8_t *uuid);
+
+/**
+ * \brief Calculate a VHD formatted timestamp from the current time
+ */
+uint32_t vhd_calc_timestamp(void);
+
+/**
+ * \brief Convert an epoch timestamp to a VHD timestamp
+ *
+ * \param [in] ts epoch timestamp to convert.
+ *
+ * \return The adjusted timestamp, or 0 if the input timestamp is
+ * earlier that 1 Janurary 2000
+ */
+uint32_t mvhd_epoch_to_vhd_ts(time_t ts);
+
+/**
+ * \brief Return the created time from a VHD image
+ *
+ * \param [in] vhdm Pointer to the MiniVHD metadata structure
+ *
+ * \return The created time, as a Unix timestamp
+ */
+time_t vhd_get_created_time(MVHDMeta *vhdm);
+
+/**
+ * \brief Cross platform, unicode filepath opening
+ *
+ * This function accounts for the fact that fopen() handles file paths differently compared to other
+ * operating systems. Windows version of fopen() will not handle multi byte encoded text like UTF-8.
+ *
+ * Unicode filepath support on Windows requires using the _wfopen() function, which expects UTF-16LE
+ * encoded path and modestring.
+ *
+ * \param [in] path The filepath to open as a UTF-8 string
+ * \param [in] mode The mode string to use (eg: "rb+"")
+ * \param [out] err The error value, if an error occurrs
+ *
+ * \return a FILE pointer if successful, NULL otherwise. If NULL, check the value of err
+ */
+FILE* mvhd_fopen(const char* path, const char* mode, int* err);
+
+void mvhd_set_encoding_err(int encoding_retval, int* err);
+
+/**
+ * \brief Generate VHD footer checksum
+ *
+ * \param [in] vhdm MiniVHD data structure
+ */
+uint32_t mvhd_gen_footer_checksum(MVHDFooter* footer);
+
+/**
+ * \brief Generate VHD sparse header checksum
+ *
+ * \param [in] vhdm MiniVHD data structure
+ */
+uint32_t mvhd_gen_sparse_checksum(MVHDSparseHeader* header);
+
+/**
+ * \brief Get current position in file stream
+ *
+ * This is a portable version of the POSIX ftello64(). *
+ */
+int64_t mvhd_ftello64(FILE* stream);
+
+/**
+ * \brief Reposition the file stream's position
+ *
+ * This is a portable version of the POSIX fseeko64(). *
+ */
+int mvhd_fseeko64(FILE* stream, int64_t offset, int origin);
+
+/**
+ * \brief Calculate the CRC32 of a data buffer.
+ *
+ * This function can be used for verifying data integrity.
+ *
+ * \param [in] data The data buffer
+ * \param [in] n_bytes The size of the data buffer in bytes
+ *
+ * \return The CRC32 of the data buffer
+ */
+uint32_t mvhd_crc32(const void* data, size_t n_bytes);
+
+/**
+ * \brief Calculate the file modification timestamp.
+ *
+ * This function is primarily to help protect differencing VHD's
+ *
+ * \param [in] path the UTF-8 file path
+ * \param [out] err The error value, if an error occurrs
+ *
+ * \return The file modified timestamp, in VHD compatible timestamp.
+ * 'err' will be set to non-zero on error
+ */
+uint32_t mvhd_file_mod_timestamp(const char* path, int *err);
+#endif
diff --git a/src/model.c b/src/model.c
index bed454f..6b9f71f 100644
--- a/src/model.c
+++ b/src/model.c
@@ -4,23 +4,33 @@
#include "io.h"
#include "mouse.h"
+#include "82091aa.h"
#include "acc2036.h"
+#include "acc2168.h"
+#include "acc3221.h"
#include "acer386sx.h"
#include "ali1429.h"
#include "amstrad.h"
#include "cbm_io.h"
#include "cmd640.h"
#include "compaq.h"
+#include "cs8230.h"
#include "dells200.h"
#include "device.h"
+#include "cassette.h"
#include "dma.h"
+#include "f82c710_upc.h"
#include "fdc.h"
#include "fdc37c665.h"
+#include "fdc37c93x.h"
#include "gameport.h"
#include "headland.h"
#include "i430fx.h"
+#include "i430hx.h"
#include "i430lx.h"
#include "i430vx.h"
+#include "i440bx.h"
+#include "i440fx.h"
#include "ide.h"
#include "intel.h"
#include "intel_flash.h"
@@ -41,6 +51,7 @@
#include "olivetti_m24.h"
#include "opti495.h"
#include "pc87306.h"
+#include "pc87307.h"
#include "pci.h"
#include "pic.h"
#include "piix.h"
@@ -48,6 +59,7 @@
#include "ps1.h"
#include "ps2.h"
#include "ps2_mca.h"
+#include "scamp.h"
#include "scat.h"
#include "serial.h"
#include "sio.h"
@@ -56,6 +68,7 @@
#include "sound_ps1.h"
#include "sound_pssj.h"
#include "sound_sn76489.h"
+#include "superxt.h"
#include "sst39sf010.h"
#include "tandy_eeprom.h"
#include "tandy_rom.h"
@@ -63,16 +76,20 @@
#include "vid_pcjr.h"
#include "vid_tandy.h"
#include "vid_t1000.h"
+#include "vl82c480.h"
#include "vt82c586b.h"
#include "w83877tf.h"
+#include "w83977tf.h"
#include "wd76c10.h"
#include "xi8088.h"
+#include "zenith.h"
void xt_init();
void pcjr_init();
void tandy1k_init();
void tandy1ksl2_init();
void ams_init();
+void pc5086_init();
void europc_init();
void olim24_init();
void at_init();
@@ -83,118 +100,154 @@ void deskpro386_init();
void pb_l300sx_init();
void ps1_m2011_init();
void ps1_m2121_init();
+void ps1_m2133_init(void);
void ps2_m30_286_init();
void ps2_model_50_init();
void ps2_model_55sx_init();
void ps2_model_70_init();
void ps2_model_80_init();
void at_neat_init();
+void at_scamp_init();
void at_scat_init();
void at_scatsx_init();
void at_acer386sx_init();
void at_wd76c10_init();
+void at_cs8230_init();
void at_ali1429_init();
void at_headland_init();
void at_opti495_init();
void at_sis496_init();
+void at_p55va_init();
+void at_p55tvp4_init();
void at_i430vx_init();
void at_batman_init();
void at_endeavor_init();
+void at_p55t2p4_init();
void xt_laserxt_init();
void at_t3100e_init();
void xt_t1000_init();
void xt_t1200_init();
void at_sl82c460_init();
void at_zappa_init();
+void at_pb410a_init();
void at_pb520r_init();
void at_pb570_init();
-void compaq_pip_init();
+void compaq_xt_init();
void xt_xi8088_init();
+void xt_zenith_init();
void at_mvp3_init();
+void at_vs440fx_init();
+void at_ga686bx_init();
int model;
-int AMSTRAD, AT, PCI, TANDY;
+int AMSTRAD, AT, PCI, TANDY, MCA;
MODEL models[] =
{
{"[8088] AMI XT clone", ROM_AMIXT, "amixt", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 64, 640, 64, xt_init, NULL},
{"[8088] Atari PC3", ROM_ATARIPC3, "ataripc3", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 64, 640, 64, xt_init, NULL},
- {"[8088] Compaq Portable Plus", ROM_COMPAQ_PIP, "compaq_pip", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 128, 640, 64, compaq_pip_init, NULL},
+ {"[8088] Compaq Portable Plus", ROM_COMPAQ_PIP, "compaq_pip", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 128, 640, 64, compaq_xt_init, NULL},
{"[8088] DTK XT clone", ROM_DTKXT, "dtk", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 64, 640, 64, xt_init, NULL},
{"[8088] Generic XT clone", ROM_GENXT, "genxt", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 32, 704, 16, xt_init, NULL},
{"[8088] IBM PC", ROM_IBMPC, "ibmpc", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 64, 640, 32, xt_init, NULL},
{"[8088] IBM PCjr", ROM_IBMPCJR, "ibmpcjr", { {"", cpus_pcjr}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED, 128, 640, 64, pcjr_init, &pcjr_device},
{"[8088] IBM XT", ROM_IBMXT, "ibmxt", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 64, 640, 64, xt_init, NULL},
{"[8088] Juko XT clone", ROM_JUKOPC, "jukopc", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 64, 640, 64, xt_init, NULL},
+ {"[8088] Leading Edge Model M", ROM_LEDGE_MODELM, "ledge_modelm", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 128, 704, 64, xt_init, NULL},
{"[8088] NCR PC4i", ROM_NCR_PC4I, "ncr_pc4i", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 256, 640, 64, xt_init, NULL},
{"[8088] Phoenix XT clone", ROM_PXXT, "pxxt", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 64, 640, 64, xt_init, NULL},
{"[8088] Schneider EuroPC", ROM_EUROPC, "europc", { {"", cpus_europc}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 512, 640, 128, europc_init, NULL},
{"[8088] Tandy 1000", ROM_TANDY, "tandy", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED, 128, 640, 128, tandy1k_init, &tandy1000_device},
{"[8088] Tandy 1000 HX", ROM_TANDY1000HX, "tandy1000hx", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED, 256, 640, 128, tandy1k_init, &tandy1000hx_device},
{"[8088] Thomson TO16 PC", ROM_TO16_PC, "to16_pc", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 512, 640, 128, xt_init, NULL},
- {"[8088] Toshiba T1000", ROM_T1000, "t1000", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED, 512, 1280, 768, xt_t1000_init, &t1000_device},
+ {"[8088] Toshiba T1000", ROM_T1000, "t1000", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED, 512, 1280, 768, xt_t1000_init, NULL},
{"[8088] VTech Laser Turbo XT", ROM_LTXT, "ltxt", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 64, 1152, 64, xt_laserxt_init, NULL},
{"[8088] Xi8088", ROM_XI8088, "xi8088", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PS2, 64, 1024, 128, xt_xi8088_init, &xi8088_device},
+ {"[8088] Zenith Data SupersPort", ROM_ZD_SUPERS, "zdsupers", { {"", cpus_8088}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 128, 640, 128, xt_zenith_init, NULL},
- {"[8086] Amstrad PC1512", ROM_PC1512, "pc1512", { {"", cpus_pc1512}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED|MODEL_AMSTRAD, 512, 640, 128, ams_init, NULL},
- {"[8086] Amstrad PC1640", ROM_PC1640, "pc1640", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_HW|MODEL_AMSTRAD, 640, 640, 0, ams_init, NULL},
- {"[8086] Amstrad PC2086", ROM_PC2086, "pc2086", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_HW|MODEL_AMSTRAD, 640, 640, 0, ams_init, NULL},
- {"[8086] Amstrad PC3086", ROM_PC3086, "pc3086", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_HW|MODEL_AMSTRAD, 640, 640, 0, ams_init, NULL},
+ {"[8086] Amstrad PC1512", ROM_PC1512, "pc1512", { {"", cpus_pc1512}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED|MODEL_AMSTRAD, 512, 640, 128, ams_init, &ams1512_device},
+ {"[8086] Amstrad PC1640", ROM_PC1640, "pc1640", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_HW|MODEL_AMSTRAD, 640, 640, 0, ams_init, &ams1512_device},
+ {"[8086] Amstrad PC2086", ROM_PC2086, "pc2086", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_HW|MODEL_AMSTRAD, 640, 640, 0, ams_init, &ams2086_device},
+ {"[8086] Amstrad PC3086", ROM_PC3086, "pc3086", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_HW|MODEL_AMSTRAD, 640, 640, 0, ams_init, &ams3086_device},
+ {"[8086] Amstrad PC5086", ROM_PC5086, "pc5086", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_PS2, 640, 640, 0, pc5086_init, &f82c710_upc_device},
+ {"[8086] Amstrad PPC512/640", ROM_PPC512, "ppc512", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_HW|MODEL_AMSTRAD, 512, 640, 128, ams_init, &ams1512_device},
+ {"[8086] Compaq Deskpro", ROM_DESKPRO, "deskpro", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 128, 640, 128, compaq_xt_init, NULL},
{"[8086] Olivetti M24", ROM_OLIM24, "olivetti_m24", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED|MODEL_OLIM24, 128, 640, 128, olim24_init, NULL},
- {"[8086] Sinclair PC200", ROM_PC200, "pc200", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_HW|MODEL_AMSTRAD, 512, 640, 128, ams_init, NULL},
+ {"[8086] Sinclair PC200", ROM_PC200, "pc200", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_HW|MODEL_AMSTRAD, 512, 640, 128, ams_init, &ams1512_device},
{"[8086] Tandy 1000 SL/2", ROM_TANDY1000SL2, "tandy1000sl2", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED, 512, 768, 128, tandy1ksl2_init, NULL},
- {"[8088] Toshiba T1200", ROM_T1200, "t1200", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED, 1024, 2048,1024, xt_t1200_init, &t1000_device},
+ {"[8088] Toshiba T1200", ROM_T1200, "t1200", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED, 1024, 2048,1024, xt_t1200_init, NULL},
{"[8086] VTech Laser XT3", ROM_LXT3, "lxt3", { {"", cpus_8086}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE, 512, 1152, 128, xt_laserxt_init, NULL},
{"[286] AMI 286 clone", ROM_AMI286, "ami286", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 512,16384, 128, at_neat_init, NULL},
{"[286] Award 286 clone", ROM_AWARD286, "award286", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 512,16384, 128, at_scat_init, NULL},
+ {"[286] Bull Micral 45", ROM_BULL_MICRAL_45, "bull_micral_45", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 1024, 6144, 128, ibm_at_init, NULL},
{"[286] Commodore PC 30 III", ROM_CMDPC30, "cmdpc30", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 640,16384, 128, at_cbm_init, NULL},
{"[286] Compaq Portable II", ROM_COMPAQ_PII, "compaq_pii", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 256,15872, 128, ibm_at_init, NULL},
{"[286] DELL System 200", ROM_DELL200, "dells200", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT, 640,16384, 128, dells200_init, NULL},
{"[286] Epson PC AX", ROM_EPSON_PCAX, "epson_pcax", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT, 256,15872, 128, at_init, NULL},
{"[286] Epson PC AX2e", ROM_EPSON_PCAX2E, "epson_pcax2e", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PS2, 256,15872, 128, at_init, NULL},
+ {"[286] Goldstar GDC-212M", ROM_GDC212M, "gdc212m", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 512, 4096, 512, at_scat_init, NULL},
{"[286] GW-286CT GEAR", ROM_GW286CT, "gw286ct", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT, 512,16384, 128, at_scat_init, NULL},
+ {"[286] Hyundai Super-286TR", ROM_HYUNDAI_SUPER286TR, "super286tr", { {"AMD", cpus_super286tr}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 1024, 4096, 128, at_scat_init, &f82c710_upc_device},
{"[286] IBM AT", ROM_IBMAT, "ibmat", { {"", cpus_ibmat}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT, 256,15872, 128, ibm_at_init, NULL},
{"[286] IBM PS/1 model 2011", ROM_IBMPS1_2011, "ibmps1es", { {"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2, 512,16384, 512, ps1_m2011_init, NULL},
{"[286] IBM PS/2 Model 30-286", ROM_IBMPS2_M30_286, "ibmps2_m30_286", { {"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2, 1, 16, 1, ps2_m30_286_init, NULL},
- {"[286] IBM PS/2 Model 50", ROM_IBMPS2_M50, "ibmps2_m50", { {"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 16, 1, ps2_model_50_init, NULL},
+ {"[286] IBM PS/2 Model 50", ROM_IBMPS2_M50, "ibmps2_m50", { {"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 16, 1, ps2_model_50_init, NULL},
{"[286] IBM XT Model 286", ROM_IBMXT286, "ibmxt286", { {"", cpus_ibmxt286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT, 256,15872, 128, ibm_at_init, NULL},
{"[286] Samsung SPC-4200P", ROM_SPC4200P, "spc4200p", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 512, 2048, 128, at_scat_init, NULL},
{"[286] Samsung SPC-4216P", ROM_SPC4216P, "spc4216p", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 5, 1, at_scat_init, NULL},
+ {"[286] Samsung SPC-4620P", ROM_SPC4620P, "spc4620p", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_HW|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 5, 1, at_scat_init, NULL},
{"[286] Toshiba T3100e", ROM_T3100E, "t3100e", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_HAS_IDE, 1024, 5120, 256, at_t3100e_init, NULL},
+ {"[286] Trigem 286M", ROM_TG286M, "tg286m", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 512, 8192, 128, at_headland_init, NULL},
+ {"[286] Tulip AT Compact", ROM_TULIP_TC7, "tulip_tc7", { {"", cpus_286}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 640,15872, 128, ibm_at_init, NULL},
{"[386SX] Acer 386SX25/N", ROM_ACER386, "acer386", { {"Intel", cpus_acer}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 16, 1, at_acer386sx_init, NULL},
+ {"[386SX] AMA-932J", ROM_AMA932J, "ama932j", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_HAS_IDE, 512, 8192, 128, at_headland_init, NULL},
{"[386SX] AMI 386SX clone", ROM_AMI386SX, "ami386", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 512,16384, 128, at_headland_init, NULL},
{"[386SX] Amstrad MegaPC", ROM_MEGAPC, "megapc", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_DISABLE_HW|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 16, 1, at_wd76c10_init, NULL},
+ {"[386SX] Commodore SL386SX-25", ROM_CBM_SL386SX25, "cbm_sl386sx25", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1024,16384, 512, at_scamp_init, NULL},
{"[386SX] DTK 386SX clone", ROM_DTK386, "dtk386", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 512,16384, 128, at_neat_init, NULL},
{"[386SX] Epson PC AX3", ROM_EPSON_PCAX3, "epson_pcax3", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_NONE|MODEL_AT, 256,15872, 128, at_init, NULL},
{"[386SX] IBM PS/1 model 2121", ROM_IBMPS1_2121, "ibmps1_2121", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 16, 1, ps1_m2121_init, NULL},
- {"[386SX] IBM PS/2 Model 55SX", ROM_IBMPS2_M55SX, "ibmps2_m55sx", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 8, 1, ps2_model_55sx_init, NULL},
+ {"[386SX] IBM PS/2 Model 55SX", ROM_IBMPS2_M55SX, "ibmps2_m55sx", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 8, 1, ps2_model_55sx_init, NULL},
{"[386SX] KMX-C-02", ROM_KMXC02, "kmxc02", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_NONE|MODEL_AT, 512,16384, 512, at_scatsx_init, NULL},
{"[386SX] Packard Bell Legend 300SX", ROM_PB_L300SX, "pb_l300sx", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 16, 1, pb_l300sx_init, NULL},
+ {"[386SX] Samsung SPC-6033P", ROM_SPC6033P, "spc6033p", { {"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}}, MODEL_GFX_DISABLE_HW|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 2, 12, 2, at_scamp_init, NULL},
{"[386DX] AMI 386DX clone", ROM_AMI386DX_OPTI495, "ami386dx", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_opti495_init, NULL},
{"[386DX] Compaq Deskpro 386", ROM_DESKPRO_386, "deskpro386", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_NONE|MODEL_AT, 1, 15, 1, deskpro386_init, NULL},
- {"[386DX] IBM PS/2 Model 70 (type 3)", ROM_IBMPS2_M70_TYPE3, "ibmps2_m70_type3", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_MCA, 2, 16, 2, ps2_model_70_init, NULL},
- {"[386DX] IBM PS/2 Model 80", ROM_IBMPS2_M80, "ibmps2_m80", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 12, 1, ps2_model_80_init, NULL},
+ {"[386DX] ECS 386/32", ROM_ECS_386_32, "ecs_386_32", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_NONE|MODEL_AT, 1, 16, 1, at_cs8230_init, NULL},
+ {"[386DX] IBM PS/2 Model 70 (type 3)", ROM_IBMPS2_M70_TYPE3, "ibmps2_m70_type3", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_MCA, 2, 16, 2, ps2_model_70_init, NULL},
+ {"[386DX] IBM PS/2 Model 80", ROM_IBMPS2_M80, "ibmps2_m80", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_MCA, 1, 12, 1, ps2_model_80_init, NULL},
{"[386DX] MR 386DX clone", ROM_MR386DX_OPTI495, "mr386dx", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_opti495_init, NULL},
+ {"[386DX] Samsung SPC-6000A", ROM_SPC6000A, "spc6000a", { {"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 1, 32, 1, at_cs8230_init, NULL},
{"[486] AMI 486 clone", ROM_AMI486, "ami486", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_ali1429_init, NULL},
{"[486] AMI WinBIOS 486", ROM_WIN486, "win486", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_NONE|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_ali1429_init, NULL},
{"[486] Award SiS 496/497", ROM_SIS496, "sis496", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_HAS_IDE, 1, 256, 1, at_sis496_init, NULL},
{"[486] Elonex PC-425X", ROM_ELX_PC425X, "elx_pc425x", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_HAS_IDE, 1, 256, 1, at_sl82c460_init, NULL},
- {"[486] IBM PS/2 Model 70 (type 4)", ROM_IBMPS2_M70_TYPE4, "ibmps2_m70_type4", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2|MODEL_MCA, 2, 16, 2, ps2_model_70_init, NULL},
+ {"[486] IBM PS/1 Model 2133 (EMEA 451)",ROM_IBMPS1_2133_451, "ibmps1_2133", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_FIXED|MODEL_AT|MODEL_PS2, 2, 64, 2, ps1_m2133_init, NULL},
+ {"[486] IBM PS/2 Model 70 (type 4)", ROM_IBMPS2_M70_TYPE4, "ibmps2_m70_type4", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_MCA, 2, 16, 2, ps2_model_70_init, NULL},
+ {"[486] Packard Bell PB410A", ROM_PB410A, "pb410a", { {"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PS2|MODEL_HAS_IDE, 1, 64, 1, at_pb410a_init, NULL},
{"[Socket 4] Intel Premiere/PCI", ROM_REVENGE, "revenge", { {"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_batman_init, NULL},
{"[Socket 4] Packard Bell PB520R",ROM_PB520R, "pb520r", { {"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_pb520r_init, NULL},
- {"[Socket 5] Intel Advanced/EV", ROM_ENDEAVOR, "endeavor", { {"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_endeavor_init, NULL},
- {"[Socket 5] Intel Advanced/ZP", ROM_ZAPPA, "zappa", { {"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_zappa_init, NULL},
- {"[Socket 5] Packard Bell PB570", ROM_PB570, "pb570", { {"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_pb570_init, NULL},
+ {"[Socket 5] Intel Advanced/EV", ROM_ENDEAVOR, "endeavor", { {"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_endeavor_init, NULL},
+ {"[Socket 5] Intel Advanced/ZP", ROM_ZAPPA, "zappa", { {"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_zappa_init, NULL},
+ {"[Socket 5] Itautec Infoway Multimidia", ROM_ITAUTEC_INFOWAYM, "infowaym",{ {"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 8, 128, 1, at_zappa_init, NULL},
+ {"[Socket 5] Packard Bell PB570", ROM_PB570, "pb570", { {"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}}, MODEL_GFX_DISABLE_SW|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_pb570_init, NULL},
- {"[Socket 7] Award 430VX PCI", ROM_430VX, "430vx", { {"Intel", cpus_Pentium}, {"AMD", cpus_K6_S7}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 128, 1, at_i430vx_init, NULL},
+ {"[Socket 7] ASUS P/I-P55TVP4", ROM_P55TVP4, "p55tvp4", { {"Intel", cpus_Pentium}, {"AMD", cpus_K6_S7}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 8, 128, 1, at_p55tvp4_init, NULL},
+ {"[Socket 7] ASUS P/I-P55T2P4", ROM_P55T2P4, "p55t2p4", { {"Intel", cpus_Pentium}, {"AMD", cpus_K6_S7}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 8, 256, 1, at_p55t2p4_init, NULL},
+ {"[Socket 7] Epox P55-VA", ROM_P55VA, "p55va", { {"Intel", cpus_Pentium}, {"AMD", cpus_K6_S7}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 8, 128, 1, at_p55va_init, NULL},
+ {"[Socket 7] Shuttle HOT-557", ROM_430VX, "430vx", { {"Intel", cpus_Pentium}, {"AMD", cpus_K6_S7}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 8, 128, 1, at_i430vx_init, NULL},
- {"[Super 7] FIC VA-503+", ROM_FIC_VA503P, "fic_va503p", { {"Intel", cpus_Pentium}, {"AMD", cpus_K6_SS7}, {"IDT", cpus_WinChip_SS7}, {"Cyrix", cpus_6x86}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 512, 1, at_mvp3_init, NULL},
+ {"[Super 7] FIC VA-503+", ROM_FIC_VA503P, "fic_va503p", { {"Intel", cpus_Pentium}, {"AMD", cpus_K6_SS7}, {"IDT", cpus_WinChip_SS7}, {"Cyrix", cpus_6x86_SS7}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 1, 512, 1, at_mvp3_init, NULL},
+
+ {"[Socket 8] Intel VS440FX", ROM_VS440FX, "vs440fx", { {"Intel", cpus_PentiumPro}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 8, 256, 8, at_vs440fx_init, NULL},
+
+ {"[Slot 1] Gigabyte GA-686BX", ROM_GA686BX, "ga686bx", { {"Intel", cpus_Slot1_100MHz}, {"VIA", cpus_VIA_100MHz}}, MODEL_GFX_NONE|MODEL_AT|MODEL_PCI|MODEL_PS2|MODEL_HAS_IDE, 8, 512, 8, at_ga686bx_init, NULL},
{"", -1, "", {{"", 0}, {"", 0}, {"", 0}}, 0,0,0, 0}
};
@@ -209,6 +262,11 @@ int model_getromset()
return models[model].id;
}
+int model_getromset_from_model(int model)
+{
+ return models[model].id;
+}
+
int model_getmodel(int romset)
{
int c = 0;
@@ -273,8 +331,8 @@ void common_init()
lpt_init();
pic_init();
pit_init();
- serial1_init(0x3f8, 4);
- serial2_init(0x2f8, 3);
+ serial1_init(0x3f8, 4, 1);
+ serial2_init(0x2f8, 3, 1);
}
void xt_init()
@@ -285,9 +343,11 @@ void xt_init()
keyboard_xt_init();
nmi_init();
device_add(&gameport_device);
+ if (romset == ROM_IBMPC)
+ device_add(&cassette_device);
}
-void compaq_pip_init()
+void compaq_xt_init()
{
xt_init();
lpt1_remove();
@@ -302,10 +362,11 @@ void pcjr_init()
pic_init();
pit_init();
pit_set_out_func(&pit, 0, pit_irq0_timer_pcjr);
- serial1_init(0x2f8, 3);
+ serial1_init(0x2f8, 3, 1);
keyboard_pcjr_init();
device_add(&sn76489_device);
nmi_mask = 0x80;
+ device_add(&cassette_device);
}
void tandy1k_init()
@@ -344,12 +405,24 @@ void ams_init()
lpt1_remove();
amstrad_init();
keyboard_amstrad_init();
- nvr_init();
- nmi_init();
- fdc_set_dskchg_activelow();
+ device_add(&nvr_device);
+ nmi_init();
+ fdc_set_dskchg_activelow();
device_add(&gameport_device);
}
+void pc5086_init()
+{
+ xt_init();
+ lpt1_remove(); /* remove LPT ports, they will be enabled by 82C710 */
+ lpt2_remove();
+ serial1_remove(); /* remove COM ports, they will be enabled by 82C710 */
+ serial2_remove();
+ device_add(&nvr_device);
+ fdc_set_dskchg_activelow();
+ superxt_init();
+}
+
void europc_init()
{
common_init();
@@ -365,7 +438,7 @@ void olim24_init()
common_init();
mem_add_bios();
keyboard_olim24_init();
- nvr_init();
+ device_add(&nvr_device);
olivetti_m24_init();
nmi_init();
device_add(&gameport_device);
@@ -377,17 +450,33 @@ void xt_laserxt_init()
laserxt_init();
}
+void xt_zenith_init() /* [8088] Zenith Data Systems SupersPort */
+{
+ dma_init();
+ fdc_add();
+ lpt_init();
+ lpt2_remove(); /* only one parallel port */
+ pic_init();
+ pit_init();
+ serial1_init(0x3f8, 4, 1); /* only one serial port */
+ mem_add_bios();
+ device_add(&zenith_scratchpad_device);
+ pit_set_out_func(&pit, 1, pit_refresh_timer_xt);
+ keyboard_xt_init();
+ nmi_init();
+}
+
void xt_xi8088_init()
{
- /* TODO: set UMBs? See if PCem always sets when we have > 640KB ram and avoids conflicts when a peripheral uses the same memory space */
common_init();
mem_add_bios();
keyboard_at_init();
keyboard_at_init_ps2();
nmi_init();
- nvr_init();
+ device_add(&nvr_device);
pic2_init();
device_add(&gameport_device);
+ device_add(&sst_39sf010_device);
}
void at_init()
@@ -398,7 +487,7 @@ void at_init()
pit_set_out_func(&pit, 1, pit_refresh_timer_at);
dma16_init();
keyboard_at_init();
- nvr_init();
+ device_add(&nvr_device);
pic2_init();
device_add(&gameport_device);
nmi_mask = 0;
@@ -436,7 +525,7 @@ void ps1_common_init()
pit_set_out_func(&pit, 1, pit_refresh_timer_at);
dma16_init();
keyboard_at_init();
- nvr_init();
+ device_add(&nvr_device);
pic2_init();
fdc_set_dskchg_activelow();
device_add(&ps1_audio_device);
@@ -458,6 +547,13 @@ void ps1_m2121_init()
fdc_set_ps1();
}
+void ps1_m2133_init(void)
+{
+ at_init();
+ vl82c480_init();
+ ps1mb_m2133_init();
+}
+
void ps2_m30_286_init()
{
AT = 1;
@@ -467,7 +563,7 @@ void ps2_m30_286_init()
dma16_init();
keyboard_at_init();
// mouse_ps2_init();
- nvr_init();
+ device_add(&nvr_device);
pic2_init();
ps2board_init();
fdc_set_dskchg_activelow();
@@ -483,7 +579,7 @@ static void ps2_common_init()
keyboard_at_init();
keyboard_at_init_ps2();
// mouse_ps2_init();
- nvr_init();
+ device_add(&nvr_device);
pic2_init();
pit_ps2_init();
@@ -521,6 +617,12 @@ void at_neat_init()
neat_init();
}
+void at_scamp_init()
+{
+ at_init();
+ scamp_init();
+}
+
void at_scat_init()
{
at_init();
@@ -557,6 +659,12 @@ void at_opti495_init()
opti495_init();
}
+void at_cs8230_init()
+{
+ at_init();
+ cs8230_init();
+}
+
void at_ali1429_init()
{
at_init();
@@ -569,6 +677,14 @@ void pb_l300sx_init()
acc2036_init();
}
+void at_pb410a_init()
+{
+ at_init();
+ acc2168_init();
+ acc3221_init();
+}
+
+
void at_sis496_init()
{
at_init();
@@ -608,6 +724,7 @@ void at_pb520r_init()
i430lx_init();
sio_init(2, 0xc, 0xe, 0x6, 0);
cmd640b_init(1);
+ aip_82091aa_init(0x22);
intel_batman_init();
device_add(&intel_flash_bxt_ami_device);
}
@@ -620,7 +737,7 @@ void at_endeavor_init()
pci_slot(0xf);
pci_slot(0x10);
i430fx_init();
- piix_init(7, 0xd, 0xe, 0xf, 0x10);
+ piix_init(7, 0xd, 0xe, 0xf, 0x10, i430fx_reset);
pc87306_init(0x2e);
intel_endeavor_init();
device_add(&intel_flash_bxt_ami_device);
@@ -632,7 +749,7 @@ void at_pb570_init()
pci_slot(0x11);
pci_slot(0x13);
i430fx_init();
- piix_init(7, 0x11, 0x13, 0xb, 0x8);
+ piix_init(7, 0x11, 0x13, 0xb, 0x8, i430fx_reset);
pc87306_init(0x2e);
intel_endeavor_init();
device_add(&intel_flash_bxt_ami_device);
@@ -646,12 +763,40 @@ void at_zappa_init()
pci_slot(0xf);
pci_slot(0x10);
i430fx_init();
- piix_init(7, 0xd, 0xf, 0xe, 0x10);
+ piix_init(7, 0xd, 0xf, 0xe, 0x10, i430fx_reset);
pc87306_init(0x2e);
intel_zappa_init();
device_add(&intel_flash_bxt_ami_device);
}
+void at_p55va_init()
+{
+ at_init();
+ pci_init(PCI_CONFIG_TYPE_1);
+ pci_slot(0x08);
+ pci_slot(0x09);
+ pci_slot(0x0A);
+ pci_slot(0x0B);
+ i430vx_init();
+ piix_init(7, 0x08, 0x09, 0x0A, 0x0B, i430vx_reset);
+ fdc37c932fr_init();
+ device_add(&intel_flash_bxt_device);
+}
+
+void at_p55tvp4_init()
+{
+ at_init();
+ pci_init(PCI_CONFIG_TYPE_1);
+ pci_slot(0x0C);
+ pci_slot(0x0B);
+ pci_slot(0x0A);
+ pci_slot(0x09);
+ i430vx_init();
+ piix_init(7, 0x0C, 0x0B, 0x0A, 0x09, i430vx_reset);
+ w83877f_init(0x3f0, 0x87);
+ device_add(&intel_flash_bxt_device);
+}
+
void at_i430vx_init()
{
at_init();
@@ -661,11 +806,25 @@ void at_i430vx_init()
pci_slot(0x13);
pci_slot(0x14);
i430vx_init();
- piix_init(7, 18, 17, 20, 19);
+ piix_init(7, 18, 17, 20, 19, i430vx_reset);
um8669f_init();
device_add(&intel_flash_bxt_device);
}
+void at_p55t2p4_init()
+{
+ at_init();
+ pci_init(PCI_CONFIG_TYPE_1);
+ pci_slot(0x0C);
+ pci_slot(0x0B);
+ pci_slot(0x0A);
+ pci_slot(0x09);
+ i430hx_init();
+ piix_init(7, 0x0C, 0x0B, 0x0A, 0x09, i430hx_reset);
+ w83877f_init(0x3f0, 0x87);
+ device_add(&intel_flash_bxt_device);
+}
+
void at_mvp3_init()
{
at_init();
@@ -675,14 +834,43 @@ void at_mvp3_init()
pci_slot(10);
mvp3_init();
vt82c586b_init(7, 8, 9, 10, 0);
- w83877tf_init();
+ w83877tf_init(0x250, 0x89);
device_add(&sst_39sf010_device);
}
+void at_vs440fx_init()
+{
+ at_init();
+ pci_init(PCI_CONFIG_TYPE_1);
+ pci_slot(0xb);
+ pci_slot(0xf);
+ pci_slot(0x11);
+ pci_slot(0x13);
+ i440fx_init();
+ piix_init(7, 0xb, 0xf, 0x11, 0x13, i440fx_reset);
+ pc87307_init(0x2e);
+// i440fx_init();
+ device_add(&intel_flash_28fb200bxt_device);
+}
+
+void at_ga686bx_init()
+{
+ at_init();
+ pci_init(PCI_CONFIG_TYPE_1);
+ pci_slot(0x8);
+ pci_slot(0x9);
+ pci_slot(0xa);
+ pci_slot(0xb);
+ i440bx_init();
+ piix4_init(7, 0x8, 0x9, 0xa, 0xb, i440bx_reset);
+ w83977tf_init(0x3f0, 0x87);
+ device_add(&intel_flash_28f002bc_device);
+}
+
void model_init()
{
pclog("Initting as %s\n", model_getname());
- AMSTRAD = AT = PCI = TANDY = 0;
+ AMSTRAD = AT = PCI = TANDY = MCA = 0;
ide_set_bus_master(NULL, NULL, NULL, NULL);
models[model].init();
diff --git a/src/model.h b/src/model.h
index 11c442d..7b568f1 100644
--- a/src/model.h
+++ b/src/model.h
@@ -39,6 +39,7 @@ extern int model;
int model_count();
int model_getromset();
+int model_getromset_from_model(int model);
int model_getmodel(int romset);
char *model_getname();
char *model_get_internal_name();
diff --git a/src/mouse_ps2.c b/src/mouse_ps2.c
index 1603cd9..28a362b 100644
--- a/src/mouse_ps2.c
+++ b/src/mouse_ps2.c
@@ -4,6 +4,8 @@
#include "mouse.h"
#include "mouse_ps2.h"
#include "plat-mouse.h"
+#include "x86.h"
+#include "f82c710_upc.h"
int mouse_scan = 0;
@@ -96,6 +98,27 @@ void mouse_ps2_write(uint8_t val, void *p)
keyboard_at_adddata_mouse(mouse->sample_rate);
break;
+ case 0xeb: /*Get mouse data*/
+ keyboard_at_adddata_mouse(0xfa);
+
+ temp = 0;
+ if (mouse->x < 0)
+ temp |= 0x10;
+ if (mouse->y < 0)
+ temp |= 0x20;
+ if (mouse_buttons & 1)
+ temp |= 1;
+ if (mouse_buttons & 2)
+ temp |= 2;
+ if ((mouse_buttons & 4) && (mouse_get_type(mouse_type) & MOUSE_TYPE_3BUTTON))
+ temp |= 4;
+ keyboard_at_adddata_mouse(temp);
+ keyboard_at_adddata_mouse(mouse->x & 0xff);
+ keyboard_at_adddata_mouse(mouse->y & 0xff);
+ if (mouse->intellimouse_mode)
+ keyboard_at_adddata_mouse(mouse->z);
+ break;
+
case 0xf2: /*Read ID*/
keyboard_at_adddata_mouse(0xfa);
if (mouse->intellimouse_mode)
@@ -123,6 +146,7 @@ void mouse_ps2_write(uint8_t val, void *p)
mouse->mode = MOUSE_STREAM;
mouse->flags = 0;
mouse->intellimouse_mode = 0;
+ mouse_queue_start = mouse_queue_end = 0;
keyboard_at_adddata_mouse(0xfa);
keyboard_at_adddata_mouse(0xaa);
keyboard_at_adddata_mouse(0x00);
@@ -153,7 +177,7 @@ void mouse_ps2_poll(int x, int y, int z, int b, void *p)
{
mouse_ps2_t *mouse = (mouse_ps2_t *)p;
uint8_t packet[3] = {0x08, 0, 0};
-
+
if (!x && !y && !z && b == mouse->b)
return;
@@ -214,8 +238,11 @@ void *mouse_ps2_init()
mouse->flags = 0;
mouse->mode = MOUSE_STREAM;
- keyboard_at_set_mouse(mouse_ps2_write, mouse);
-
+ if(romset == ROM_PC5086)
+ upc_set_mouse(mouse_ps2_write, mouse);
+ else
+ keyboard_at_set_mouse(mouse_ps2_write, mouse);
+
return mouse;
}
diff --git a/src/mvp3.c b/src/mvp3.c
index 2760d99..f2d77b1 100644
--- a/src/mvp3.c
+++ b/src/mvp3.c
@@ -107,6 +107,16 @@ static void mvp3_host_bridge_write(int addr, uint8_t val)
if ((mvp3.host_bridge_regs[0x63] ^ val) & 0xc0)
mvp3_map(0xe0000, 0x10000, (val & 0xc0) >> 6);
mvp3.host_bridge_regs[0x63] = val;
+ if ((val & 3) == 1 || ((val & 3) == 3 && (cpu_cur_status & CPU_STATUS_SMM))) /*SMRAM enabled*/
+ {
+ pclog("Enable SMRAM\n");
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ }
+ else
+ {
+ pclog("Disable SMRAM\n");
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ }
// if (val == 0xb0)
// output = 3;
return;
@@ -169,6 +179,17 @@ static void mvp3_write(int func, int addr, uint8_t val, void *priv)
}
}
+static void mvp3_smram_enable(void)
+{
+ if ((mvp3.host_bridge_regs[0x63] & 3) == 3)
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+}
+static void mvp3_smram_disable(void)
+{
+ if ((mvp3.host_bridge_regs[0x63] & 3) != 1)
+ mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+}
+
void mvp3_init()
{
pci_add_specific(0, mvp3_read, mvp3_write, NULL);
@@ -216,4 +237,7 @@ void mvp3_init()
mvp3.pci_bridge_regs[0x24] = 0xf0;
mvp3.pci_bridge_regs[0x25] = 0xff;
+
+ smram_enable = mvp3_smram_enable;
+ smram_disable = mvp3_smram_disable;
}
diff --git a/src/ne2000.c b/src/ne2000.c
index 329af7e..2622f2b 100644
--- a/src/ne2000.c
+++ b/src/ne2000.c
@@ -2010,6 +2010,10 @@ static device_config_t ne2000_config[] =
.description = "IRQ 11",
.value = 11
},
+ {
+ .description = "IRQ 12",
+ .value = 12
+ },
{
.description = ""
}
diff --git a/src/nvr.c b/src/nvr.c
index fe89377..edbd35b 100644
--- a/src/nvr.c
+++ b/src/nvr.c
@@ -1,5 +1,7 @@
#include
+#include
#include "ibm.h"
+#include "device.h"
#include "io.h"
#include "nvr.h"
#include "nvr_tc8521.h"
@@ -20,10 +22,14 @@ int nvraddr;
int nvr_dosave = 0;
-static pc_timer_t nvr_onesec_timer;
-static int nvr_onesec_cnt = 0;
+typedef struct nvr_t
+{
+ pc_timer_t rtc_timer;
+ pc_timer_t onesec_timer;
+ pc_timer_t update_end_timer;
-static pc_timer_t rtc_timer;
+ int onesec_cnt;
+} nvr_t;
FILE *nvrfopen(char *fn, char *mode)
{
@@ -42,11 +48,7 @@ FILE *nvrfopen(char *fn, char *mode)
if (mode[0] == 'r')
{
- strcpy(s, nvr_path);
- put_backslash(s);
- strcat(s, "default");
- put_backslash(s);
- strcat(s, fn);
+ snprintf(s, 512, "%s%s", nvr_default_path, fn);
return fopen(s, mode);
}
else
@@ -61,32 +63,44 @@ void getnvrtime()
time_get(nvrram);
}
-void nvr_recalc()
+static void nvr_speed_changed(void *p)
{
- int c;
+ nvr_t *nvr = (nvr_t *)p;
- c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1);
- timer_set_delay_u64(&rtc_timer, (uint64_t)(RTCCONST * c));
-}
-
-void nvr_rtc(void *p)
-{
- int c;
if (!(nvrram[RTC_REGA] & RTC_RS))
{
- timer_disable(&rtc_timer);
+ timer_disable(&nvr->rtc_timer);
return;
}
- c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1);
- timer_advance_u64(&rtc_timer, (uint64_t)(RTCCONST * c));
-// pclog("RTCtime now %f\n",rtctime);
- nvrram[RTC_REGC] |= RTC_PF;
- if (nvrram[RTC_REGB] & RTC_PIE)
+ else
{
- nvrram[RTC_REGC] |= RTC_IRQF;
- if (AMSTRAD) picint(2);
- else picint(0x100);
-// pclog("RTC int\n");
+ int c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1);
+ timer_set_delay_u64(&nvr->rtc_timer, (uint64_t)(RTCCONST * c));
+ }
+}
+
+static void nvr_rtc(void *p)
+{
+ nvr_t *nvr = (nvr_t *)p;
+
+ if (!(nvrram[RTC_REGA] & RTC_RS))
+ {
+ timer_disable(&nvr->rtc_timer);
+ return;
+ }
+ else
+ {
+ int c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1);
+ timer_advance_u64(&nvr->rtc_timer, (uint64_t)(RTCCONST * c));
+// pclog("RTCtime now %f\n",rtctime);
+ nvrram[RTC_REGC] |= RTC_PF;
+ if (nvrram[RTC_REGB] & RTC_PIE)
+ {
+ nvrram[RTC_REGC] |= RTC_IRQF;
+ if (AMSTRAD) picint(2);
+ else picint(0x100);
+// pclog("RTC int\n");
+ }
}
}
@@ -99,10 +113,11 @@ int nvr_check_alarm(int nvraddr)
return (nvrram[nvraddr + 1] == nvrram[nvraddr] || (nvrram[nvraddr + 1] & ALARM_DONTCARE) == ALARM_DONTCARE);
}
-pc_timer_t nvr_update_end_timer;
-void nvr_update_end(void *p)
+static void nvr_update_end(void *p)
{
+// nvr_t *nvr = (nvr_t *)p;
+
if (!(nvrram[RTC_REGB] & RTC_SET))
{
getnvrtime();
@@ -133,25 +148,28 @@ void nvr_update_end(void *p)
// pclog("RTC onesec\n");
}
-void nvr_onesec(void *p)
+static void nvr_onesec(void *p)
{
- nvr_onesec_cnt++;
- if (nvr_onesec_cnt >= 100)
+ nvr_t *nvr = (nvr_t *)p;
+
+ nvr->onesec_cnt++;
+ if (nvr->onesec_cnt >= 100)
{
if (!(nvrram[RTC_REGB] & RTC_SET))
{
nvr_update_status = RTC_UIP;
rtc_tick();
- timer_set_delay_u64(&nvr_update_end_timer, (uint64_t)((244.0 + 1984.0) * TIMER_USEC));
+ timer_set_delay_u64(&nvr->update_end_timer, (uint64_t)((244.0 + 1984.0) * TIMER_USEC));
}
- nvr_onesec_cnt = 0;
+ nvr->onesec_cnt = 0;
}
- timer_advance_u64(&nvr_onesec_timer, (uint64_t)(10000 * TIMER_USEC));
+ timer_advance_u64(&nvr->onesec_timer, (uint64_t)(10000 * TIMER_USEC));
}
-void writenvr(uint16_t addr, uint8_t val, void *priv)
+static void writenvr(uint16_t addr, uint8_t val, void *p)
{
+ nvr_t *nvr = (nvr_t *)p;
int c, old;
cycles -= ISA_CYCLES(8);
@@ -173,10 +191,10 @@ void writenvr(uint16_t addr, uint8_t val, void *priv)
if (val & RTC_RS)
{
c = 1 << ((val & RTC_RS) - 1);
- timer_set_delay_u64(&rtc_timer, (uint64_t)(RTCCONST * c));
+ timer_set_delay_u64(&nvr->rtc_timer, (uint64_t)(RTCCONST * c));
}
else
- timer_disable(&rtc_timer);
+ timer_disable(&nvr->rtc_timer);
}
else
{
@@ -210,13 +228,21 @@ void writenvr(uint16_t addr, uint8_t val, void *priv)
are always enabled for PS/2 machines - this would mean that other peripherals
could fire NMIs regardless of the mask state, but as there aren't any emulated
MCA peripherals that do this it's currently a moot point.*/
- if (!(models[model].flags & MODEL_MCA))
+
+ /* Also don't update the NMI mask on Amstrad PCs - actually
+ * ought not to do it for any XT because their NMI mask
+ * register is at 0xA0. But particularly important on the
+ * PC200 and PPC because their video subsystem issues NMIs */
+ if (!(models[model].flags & (MODEL_MCA | MODEL_AMSTRAD)))
+ {
nmi_mask = ~val & 0x80;
+ }
}
}
-uint8_t readnvr(uint16_t addr, void *priv)
+uint8_t readnvr(uint16_t addr, void *p)
{
+// nvr_t *nvr = (nvr_t *)p;
uint8_t temp;
// printf("Read NVR %03X %02X %02X %04X:%04X\n",addr,nvraddr,nvrram[nvraddr],cs>>4,pc);
cycles -= ISA_CYCLES(8);
@@ -244,7 +270,7 @@ uint8_t readnvr(uint16_t addr, void *priv)
void loadnvr()
{
FILE *f;
- int c;
+
nvrmask=63;
oldromset=romset;
switch (romset)
@@ -254,6 +280,8 @@ void loadnvr()
case ROM_PC200: f = nvrfopen("pc200.nvr", "rb"); break;
case ROM_PC2086: f = nvrfopen("pc2086.nvr", "rb"); break;
case ROM_PC3086: f = nvrfopen("pc3086.nvr", "rb"); break;
+ case ROM_PC5086: f = nvrfopen("pc5086.nvr", "rb"); break;
+ case ROM_PPC512: f = nvrfopen("ppc512.nvr", "rb"); break;
case ROM_IBMAT: f = nvrfopen("at.nvr", "rb"); break;
case ROM_IBMXT286: f = nvrfopen("ibmxt286.nvr", "rb"); break;
case ROM_IBMPS1_2011: f = nvrfopen("ibmps1_2011.nvr", "rb"); /*nvrmask = 127; */break;
@@ -264,24 +292,34 @@ void loadnvr()
case ROM_IBMPS2_M80: f = nvrfopen("ibmps2_m80.nvr", "rb"); break;
case ROM_CMDPC30: f = nvrfopen("cmdpc30.nvr", "rb"); nvrmask = 127; break;
case ROM_AMI286: f = nvrfopen("ami286.nvr", "rb"); nvrmask = 127; break;
+ case ROM_TG286M: f = nvrfopen("tg286m.nvr", "rb"); nvrmask = 127; break;
case ROM_AWARD286: f = nvrfopen("award286.nvr", "rb"); nvrmask = 127; break;
+ case ROM_GDC212M: f = nvrfopen("gdc212m.nvr", "rb"); nvrmask = 127; break;
+ case ROM_HYUNDAI_SUPER286TR: f = nvrfopen("super286tr.nvr", "rb"); nvrmask = 127; break;
case ROM_GW286CT: f = nvrfopen("gw286ct.nvr", "rb"); nvrmask = 127; break;
case ROM_SPC4200P: f = nvrfopen("spc4200p.nvr", "rb"); nvrmask = 127; break;
case ROM_SPC4216P: f = nvrfopen("spc4216p.nvr", "rb"); nvrmask = 127; break;
+ case ROM_SPC4620P: f = nvrfopen("spc4620p.nvr", "rb"); nvrmask = 127; break;
+ case ROM_SPC6000A: f = nvrfopen("spc6000a.nvr", "rb"); nvrmask = 127; break;
+ case ROM_SPC6033P: f = nvrfopen("spc6033p.nvr", "rb"); nvrmask = 127; break;
case ROM_DELL200: f = nvrfopen("dell200.nvr", "rb"); nvrmask = 127; break;
case ROM_IBMAT386: f = nvrfopen("at386.nvr", "rb"); nvrmask = 127; break;
case ROM_DESKPRO_386: f = nvrfopen("deskpro386.nvr", "rb"); break;
case ROM_ACER386: f = nvrfopen("acer386.nvr", "rb"); nvrmask = 127; break;
case ROM_KMXC02: f = nvrfopen("kmxc02.nvr", "rb"); nvrmask = 127; break;
case ROM_MEGAPC: f = nvrfopen("megapc.nvr", "rb"); nvrmask = 127; break;
+ case ROM_AMA932J: f = nvrfopen("ama932j.nvr", "rb"); nvrmask = 127; break;
case ROM_AMI386SX: f = nvrfopen("ami386.nvr", "rb"); nvrmask = 127; break;
case ROM_AMI486: f = nvrfopen("ami486.nvr", "rb"); nvrmask = 127; break;
case ROM_WIN486: f = nvrfopen("win486.nvr", "rb"); nvrmask = 127; break;
case ROM_PCI486: f = nvrfopen("hot-433.nvr", "rb"); nvrmask = 127; break;
case ROM_SIS496: f = nvrfopen("sis496.nvr", "rb"); nvrmask = 127; break;
+ case ROM_P55VA: f = nvrfopen("p55va.nvr", "rb"); nvrmask = 127; break;
+ case ROM_P55TVP4: f = nvrfopen("p55tvp4.nvr", "rb"); nvrmask = 127; break;
case ROM_430VX: f = nvrfopen("430vx.nvr", "rb"); nvrmask = 127; break;
case ROM_REVENGE: f = nvrfopen("revenge.nvr", "rb"); nvrmask = 127; break;
case ROM_ENDEAVOR: f = nvrfopen("endeavor.nvr", "rb"); nvrmask = 127; break;
+ case ROM_P55T2P4: f = nvrfopen("p55t2p4.nvr", "rb"); nvrmask = 127; break;
case ROM_PX386: f = nvrfopen("px386.nvr", "rb"); nvrmask = 127; break;
case ROM_DTK386: f = nvrfopen("dtk386.nvr", "rb"); nvrmask = 127; break;
case ROM_MR386DX_OPTI495: f = nvrfopen("mr386dx_opti495.nvr", "rb"); nvrmask = 127; break;
@@ -303,11 +341,20 @@ void loadnvr()
case ROM_ELX_PC425X: f = nvrfopen("elx_pc425.nvr", "rb"); nvrmask = 127; break;
case ROM_PB570: f = nvrfopen("pb570.nvr", "rb"); nvrmask = 127; break;
case ROM_ZAPPA: f = nvrfopen("zappa.nvr", "rb"); nvrmask = 127; break;
+ case ROM_ITAUTEC_INFOWAYM: f = nvrfopen("infowaym.nvr", "rb"); nvrmask = 127; break;
case ROM_PB520R: f = nvrfopen("pb520r.nvr", "rb"); nvrmask = 127; break;
case ROM_XI8088: f = nvrfopen("xi8088.nvr", "rb"); nvrmask = 127; break;
case ROM_IBMPS2_M70_TYPE3: f = nvrfopen("ibmps2_m70_type3.nvr","rb"); break;
case ROM_IBMPS2_M70_TYPE4: f = nvrfopen("ibmps2_m70_type4.nvr","rb"); break;
+ case ROM_TULIP_TC7: f = nvrfopen("tulip_tc7.nvr", "rb"); break;
+ case ROM_PB410A: f = nvrfopen("pb410a.nvr", "rb"); nvrmask = 127; break;
+ case ROM_BULL_MICRAL_45: f = nvrfopen("bull_micral_45.nvr", "rb"); break;
case ROM_FIC_VA503P: f = nvrfopen("fic_va503p.nvr", "rb"); nvrmask = 127; break;
+ case ROM_CBM_SL386SX25: f = nvrfopen("cbm_sl386sx25.nvr", "rb"); nvrmask = 127; break;
+ case ROM_IBMPS1_2133_451: f = nvrfopen("ibmps1_2133.nvr", "rb"); nvrmask = 127; break;
+ case ROM_ECS_386_32: f = nvrfopen("ecs_386_32.nvr", "rb"); nvrmask = 127; break;
+ case ROM_VS440FX: f = nvrfopen("vs440fx.nvr", "rb"); nvrmask = 127; break;
+ case ROM_GA686BX: f = nvrfopen("ga686bx.nvr", "rb"); nvrmask = 127; break;
default: return;
}
@@ -332,8 +379,6 @@ void loadnvr()
fclose(f);
nvrram[RTC_REGA] = 6;
nvrram[RTC_REGB] = RTC_2412;
- c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1);
- timer_set_delay_u64(&rtc_timer, (uint64_t)(RTCCONST * c));
}
void savenvr()
{
@@ -345,6 +390,8 @@ void savenvr()
case ROM_PC200: f = nvrfopen("pc200.nvr", "wb"); break;
case ROM_PC2086: f = nvrfopen("pc2086.nvr", "wb"); break;
case ROM_PC3086: f = nvrfopen("pc3086.nvr", "wb"); break;
+ case ROM_PC5086: f = nvrfopen("pc5086.nvr", "wb"); break;
+ case ROM_PPC512: f = nvrfopen("ppc512.nvr", "wb"); break;
case ROM_IBMAT: f = nvrfopen("at.nvr", "wb"); break;
case ROM_IBMXT286: f = nvrfopen("ibmxt286.nvr", "wb"); break;
case ROM_IBMPS1_2011: f = nvrfopen("ibmps1_2011.nvr", "wb"); break;
@@ -355,24 +402,34 @@ void savenvr()
case ROM_IBMPS2_M80: f = nvrfopen("ibmps2_m80.nvr", "wb"); break;
case ROM_CMDPC30: f = nvrfopen("cmdpc30.nvr", "wb"); break;
case ROM_AMI286: f = nvrfopen("ami286.nvr", "wb"); break;
+ case ROM_TG286M: f = nvrfopen("tg286m.nvr", "wb"); break;
case ROM_AWARD286: f = nvrfopen("award286.nvr", "wb"); break;
+ case ROM_GDC212M: f = nvrfopen("gdc212m.nvr", "wb"); break;
+ case ROM_HYUNDAI_SUPER286TR: f = nvrfopen("super286tr.nvr", "wb"); break;
case ROM_GW286CT: f = nvrfopen("gw286ct.nvr", "wb"); break;
case ROM_SPC4200P: f = nvrfopen("spc4200p.nvr", "wb"); break;
case ROM_SPC4216P: f = nvrfopen("spc4216p.nvr", "wb"); break;
+ case ROM_SPC4620P: f = nvrfopen("spc4620p.nvr", "wb"); break;
+ case ROM_SPC6000A: f = nvrfopen("spc6000a.nvr", "wb"); break;
+ case ROM_SPC6033P: f = nvrfopen("spc6033p.nvr", "wb"); break;
case ROM_DELL200: f = nvrfopen("dell200.nvr", "wb"); break;
case ROM_IBMAT386: f = nvrfopen("at386.nvr", "wb"); break;
case ROM_DESKPRO_386: f = nvrfopen("deskpro386.nvr", "wb"); break;
case ROM_ACER386: f = nvrfopen("acer386.nvr", "wb"); break;
case ROM_KMXC02: f = nvrfopen("kmxc02.nvr", "wb"); break;
case ROM_MEGAPC: f = nvrfopen("megapc.nvr", "wb"); break;
+ case ROM_AMA932J: f = nvrfopen("ama932j.nvr", "wb"); break;
case ROM_AMI386SX: f = nvrfopen("ami386.nvr", "wb"); break;
case ROM_AMI486: f = nvrfopen("ami486.nvr", "wb"); break;
case ROM_WIN486: f = nvrfopen("win486.nvr", "wb"); break;
case ROM_PCI486: f = nvrfopen("hot-433.nvr", "wb"); break;
case ROM_SIS496: f = nvrfopen("sis496.nvr", "wb"); break;
+ case ROM_P55VA: f = nvrfopen("p55va.nvr", "wb"); break;
+ case ROM_P55TVP4: f = nvrfopen("p55tvp4.nvr", "wb"); break;
case ROM_430VX: f = nvrfopen("430vx.nvr", "wb"); break;
case ROM_REVENGE: f = nvrfopen("revenge.nvr", "wb"); break;
case ROM_ENDEAVOR: f = nvrfopen("endeavor.nvr", "wb"); break;
+ case ROM_P55T2P4: f = nvrfopen("p55t2p4.nvr", "wb"); break;
case ROM_PX386: f = nvrfopen("px386.nvr", "wb"); break;
case ROM_DTK386: f = nvrfopen("dtk386.nvr", "wb"); break;
case ROM_MR386DX_OPTI495: f = nvrfopen("mr386dx_opti495.nvr", "wb"); break;
@@ -394,11 +451,20 @@ void savenvr()
case ROM_ELX_PC425X: f = nvrfopen("elx_pc425.nvr", "wb"); break;
case ROM_PB570: f = nvrfopen("pb570.nvr", "wb"); break;
case ROM_ZAPPA: f = nvrfopen("zappa.nvr", "wb"); break;
+ case ROM_ITAUTEC_INFOWAYM: f = nvrfopen("infowaym.nvr", "wb"); break;
case ROM_PB520R: f = nvrfopen("pb520r.nvr", "wb"); break;
case ROM_XI8088: f = nvrfopen("xi8088.nvr", "wb"); break;
case ROM_IBMPS2_M70_TYPE3: f = nvrfopen("ibmps2_m70_type3.nvr","wb"); break;
case ROM_IBMPS2_M70_TYPE4: f = nvrfopen("ibmps2_m70_type4.nvr","wb"); break;
+ case ROM_TULIP_TC7: f = nvrfopen("tulip_tc7.nvr", "wb"); break;
+ case ROM_PB410A: f = nvrfopen("pb410a.nvr", "wb"); break;
+ case ROM_BULL_MICRAL_45: f = nvrfopen("bull_micral_45.nvr", "wb"); break;
case ROM_FIC_VA503P: f = nvrfopen("fic_va503p.nvr", "wb"); break;
+ case ROM_CBM_SL386SX25: f = nvrfopen("cbm_sl386sx25.nvr", "wb"); break;
+ case ROM_IBMPS1_2133_451: f = nvrfopen("ibmps1_2133.nvr", "wb"); break;
+ case ROM_ECS_386_32: f = nvrfopen("ecs_386_32.nvr", "wb"); break;
+ case ROM_VS440FX: f = nvrfopen("vs440fx.nvr", "wb"); break;
+ case ROM_GA686BX: f = nvrfopen("ga686bx.nvr", "wb"); break;
default: return;
}
@@ -406,11 +472,35 @@ void savenvr()
fclose(f);
}
-void nvr_init()
+static void *nvr_init()
{
- io_sethandler(0x0070, 0x0002, readnvr, NULL, NULL, writenvr, NULL, NULL, NULL);
- timer_add(&rtc_timer, nvr_rtc, NULL, 1);
- timer_add(&nvr_onesec_timer, nvr_onesec, NULL, 1);
- timer_add(&nvr_update_end_timer, nvr_update_end, NULL, 0);
+ nvr_t *nvr = (nvr_t *)malloc(sizeof(nvr_t));
+ memset(nvr, 0, sizeof(nvr_t));
+ io_sethandler(0x0070, 0x0002, readnvr, NULL, NULL, writenvr, NULL, NULL, nvr);
+ timer_add(&nvr->rtc_timer, nvr_rtc, nvr, 1);
+ timer_add(&nvr->onesec_timer, nvr_onesec, nvr, 1);
+ timer_add(&nvr->update_end_timer, nvr_update_end, nvr, 0);
+
+ return nvr;
}
+
+static void nvr_close(void *p)
+{
+ nvr_t *nvr = (nvr_t *)p;
+
+ free(nvr);
+}
+
+device_t nvr_device =
+{
+ "Motorola MC146818 RTC",
+ 0,
+ nvr_init,
+ nvr_close,
+ NULL,
+ nvr_speed_changed,
+ NULL,
+ NULL,
+ NULL
+};
diff --git a/src/nvr.h b/src/nvr.h
index f92942b..b01d7df 100644
--- a/src/nvr.h
+++ b/src/nvr.h
@@ -1,4 +1,6 @@
-void nvr_init();
+#include "device.h"
+
+extern device_t nvr_device;
extern int enable_sync;
@@ -7,8 +9,6 @@ extern int nvr_dosave;
void loadnvr();
void savenvr();
-void nvr_recalc();
-
FILE *nvrfopen(char *fn, char *mode);
extern uint8_t nvrram[128];
diff --git a/src/paths.c b/src/paths.c
index e3265b8..15d9963 100644
--- a/src/paths.c
+++ b/src/paths.c
@@ -25,6 +25,8 @@ char logs_path[512];
/* this is where screenshots as stored */
char screenshots_path[512];
+char nvr_default_path[512];
+
char get_path_separator()
{
#ifdef _WIN32
@@ -129,6 +131,11 @@ void set_default_nvr_path(char *s)
set_nvr_path(s);
}
+static void set_default_nvr_default_path(char *s)
+{
+ safe_strncpy(nvr_default_path, s, 512);
+}
+
/* set the default logs path, this makes it permanent */
void set_default_logs_path(char *s)
{
@@ -203,6 +210,7 @@ void paths_onconfigloaded()
void paths_init()
{
char s[512];
+ char base_path[512];
char *p;
get_pcem_path(pcem_path, 512);
@@ -221,6 +229,10 @@ void paths_init()
set_screenshots_path(s);
set_logs_path(pcem_path);
+ get_pcem_base_path(base_path, 512);
+ append_filename(s, base_path, "nvr/default/", 512);
+ set_default_nvr_default_path(s);
+
add_config_callback(paths_loadconfig, paths_saveconfig, paths_onconfigloaded);
}
diff --git a/src/paths.h b/src/paths.h
index ba54344..bf18630 100644
--- a/src/paths.h
+++ b/src/paths.h
@@ -4,8 +4,10 @@ extern char configs_path[512];
extern char nvr_path[512];
extern char logs_path[512];
extern char screenshots_path[512];
+extern char nvr_default_path[512];
void get_pcem_path(char *s, int size);
+void get_pcem_base_path(char *s, int size);
char get_path_separator();
void paths_init();
int dir_exists(char* path);
diff --git a/src/pc.c b/src/pc.c
index a259bc9..dbe1633 100644
--- a/src/pc.c
+++ b/src/pc.c
@@ -1,12 +1,20 @@
#include
#include
#include
+#ifdef __APPLE__
+#include
+#include
+#ifdef __aarch64__
+#include
+#endif
+#endif
#include "ibm.h"
#include "device.h"
#include "ali1429.h"
#include "cdrom-ioctl.h"
#include "cdrom-image.h"
+#include "cpu.h"
#include "disc.h"
#include "disc_img.h"
#include "mem.h"
@@ -104,7 +112,7 @@ void pclog(const char *format, ...)
vsprintf(buf, format, ap);
va_end(ap);
fputs(buf,pclogf);
- //fflush(pclogf);
+// fflush(pclogf);
#endif
}
@@ -304,9 +312,17 @@ void initpc(int argc, char *argv[])
initvideo();
mem_init();
loadbios();
- mem_add_bios();
+
+ // this is now done per-model
+ //mem_add_bios();
+#if defined(__APPLE__) && defined(__aarch64__)
+ pthread_jit_write_protect_np(0);
+#endif
codegen_init();
+#if defined(__APPLE__) && defined(__aarch64__)
+ pthread_jit_write_protect_np(1);
+#endif
timer_reset();
sound_reset();
@@ -388,12 +404,12 @@ void resetpc()
void resetpc_cad()
{
- keyboard_send(29); /* Ctrl key pressed */
- keyboard_send(56); /* Alt key pressed */
- keyboard_send(83); /* Delete key pressed */
- keyboard_send(157); /* Ctrl key released */
- keyboard_send(184); /* Alt key released */
- keyboard_send(211); /* Delete key released */
+ keyboard_send_scancode(29, 0); /* Ctrl key pressed */
+ keyboard_send_scancode(56, 0); /* Alt key pressed */
+ keyboard_send_scancode(83, 0); /* Delete key pressed */
+ keyboard_send_scancode(29, 1); /* Ctrl key released */
+ keyboard_send_scancode(56, 1); /* Alt key released */
+ keyboard_send_scancode(83, 1); /* Delete key released */
}
void resetpchard()
@@ -412,9 +428,9 @@ void resetpchard()
disc_load(0, discfns[0]);
disc_load(1, discfns[1]);
- model_init();
- if (!AT)
+ if (!AT && models[model].max_ram > 640 && models[model].max_ram <= 768 && !video_is_ega_vga())
mem_set_704kb();
+ model_init();
mouse_emu_init();
video_init();
speaker_init();
@@ -488,6 +504,8 @@ void resetpchard()
sound_update_buf_length();
cpu_set_turbo(1);
+
+ cycles = cycles_main = 0;
}
char romsets[17][40]={"IBM PC","IBM XT","Generic Turbo XT","Euro PC","Tandy 1000","Amstrad PC1512","Sinclair PC200","Amstrad PC1640","IBM AT","AMI 286 clone","Dell System 200","Misc 286","IBM AT 386","Misc 386","386 clone","486 clone","486 clone 2"};
@@ -507,6 +525,14 @@ int serial_fifo_read, serial_fifo_write;
int emu_fps = 0;
+#ifdef __APPLE__
+static void _set_window_title(void *s)
+{
+ set_window_title((const char *)s);
+ free(s);
+}
+#endif
+
void runpc()
{
char s[200];
@@ -581,8 +607,13 @@ void runpc()
if (win_title_update)
{
win_title_update=0;
- sprintf(s, "PCem v14 - %i%% - %s - %s - %s", fps, model_getname(), models[model].cpu[cpu_manufacturer].cpus[cpu].name, (!mousecapture) ? "Click to capture mouse" : ((mouse_get_type(mouse_type) & MOUSE_TYPE_3BUTTON) ? "Press CTRL-END to release mouse" : "Press CTRL-END or middle button to release mouse"));
+ sprintf(s, "PCem " PCEM_VERSION_STRING " - %i%% - %s - %s - %s", fps, model_getname(), models[model].cpu[cpu_manufacturer].cpus[cpu].name, (!mousecapture) ? "Click to capture mouse" : ((mouse_get_type(mouse_type) & MOUSE_TYPE_3BUTTON) ? "Press CTRL-END to release mouse" : "Press CTRL-END or middle button to release mouse"));
+#ifdef __APPLE__
+ // Needed due to modifying the UI on the non-main thread is a big no-no.
+ dispatch_async_f(dispatch_get_main_queue(), strdup(s), _set_window_title);
+#else
set_window_title(s);
+#endif
}
done++;
}
@@ -592,7 +623,7 @@ void fullspeed()
cpuspeed2=cpuspeed;
if (!atfullspeed)
{
- printf("Set fullspeed - %i %i %i\n",is386,AT,cpuspeed2);
+ pclog("Set fullspeed - %i %i %i\n",is386,AT,cpuspeed2);
if (AT)
setpitclock(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed);
else
@@ -601,7 +632,6 @@ void fullspeed()
// else setpitclock(clocks[AT?1:0][cpuspeed2][0]);
}
atfullspeed=1;
- nvr_recalc();
}
void speedchanged()
@@ -610,7 +640,6 @@ void speedchanged()
setpitclock(models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed);
else
setpitclock(14318184.0);
- nvr_recalc();
}
void closepc()
@@ -711,6 +740,8 @@ void loadconfig(char *fn)
romset = model_getromset();
cpu_manufacturer = config_get_int(CFG_MACHINE, NULL, "cpu_manufacturer", 0);
cpu = config_get_int(CFG_MACHINE, NULL, "cpu", 0);
+ p = (char *)config_get_string(CFG_MACHINE, NULL, "fpu", "none");
+ fpu_type = fpu_get_type(model, cpu_manufacturer, cpu, p);
cpu_use_dynarec = config_get_int(CFG_MACHINE, NULL, "cpu_use_dynarec", 0);
cpu_waitstates = config_get_int(CFG_MACHINE, NULL, "cpu_waitstates", 0);
@@ -807,6 +838,7 @@ void loadconfig(char *fn)
bpb_disable = config_get_int(CFG_MACHINE, NULL, "bpb_disable", 0);
cd_speed = config_get_int(CFG_MACHINE, NULL, "cd_speed", 24);
+ cd_model = cd_model_from_config((char *)config_get_string(CFG_MACHINE, NULL, "cd_model", cd_get_config_model(0)));
joystick_type = config_get_int(CFG_MACHINE, NULL, "joystick_type", 0);
mouse_type = config_get_int(CFG_MACHINE, NULL, "mouse_type", 0);
@@ -901,6 +933,7 @@ void saveconfig(char *fn)
config_set_string(CFG_MACHINE, NULL, "model", model_get_internal_name());
config_set_int(CFG_MACHINE, NULL, "cpu_manufacturer", cpu_manufacturer);
config_set_int(CFG_MACHINE, NULL, "cpu", cpu);
+ config_set_string(CFG_MACHINE, NULL, "fpu", (char *)fpu_get_internal_name(model, cpu_manufacturer, cpu, fpu_type));
config_set_int(CFG_MACHINE, NULL, "cpu_use_dynarec", cpu_use_dynarec);
config_set_int(CFG_MACHINE, NULL, "cpu_waitstates", cpu_waitstates);
@@ -953,6 +986,7 @@ void saveconfig(char *fn)
config_set_int(CFG_MACHINE, NULL, "bpb_disable", bpb_disable);
config_set_int(CFG_MACHINE, NULL, "cd_speed", cd_speed);
+ config_set_string(CFG_MACHINE, NULL, "cd_model", cd_model_to_config(cd_model));
config_set_int(CFG_MACHINE, NULL, "joystick_type", joystick_type);
config_set_int(CFG_MACHINE, NULL, "mouse_type", mouse_type);
diff --git a/src/pc.rc b/src/pc.rc
index 0334579..b011d54 100644
--- a/src/pc.rc
+++ b/src/pc.rc
@@ -24,6 +24,11 @@ BEGIN
MENUITEM SEPARATOR
MENUITEM "&Configure hard discs...",IDM_HDCONF
END
+ POPUP "C&assette"
+ BEGIN
+ MENUITEM "&Load tapefile...", IDM_CASSETTE_LOAD
+ MENUITEM "&Eject tape", IDM_CASSETTE_EJECT
+ END
POPUP "&Settings"
BEGIN
MENUITEM "&Configure...", IDM_CONFIG
diff --git a/src/pc.xrc b/src/pc.xrc
index 66b6ca8..88e234c 100644
--- a/src/pc.xrc
+++ b/src/pc.xrc
@@ -137,6 +137,15 @@
1
+
+
+ 0
+ wxALL | wxALIGN_CENTER_VERTICAL
+ 5
+
+ Block size:
+ -1
+
+
+
+ 0
+ wxALL
+ 5
+
+
+ 350,-1
+
+
+
+
+
+ 1
+ wxEXPAND
+ 5
+ 0,0
+
@@ -3549,7 +3683,7 @@
wxALL
5
- PCem v14\nhttps://pcem-emulator.co.uk/\n\nThis program is licensed under the GNU General Public License version 2.\nSee COPYING for more details.\n\nToolbar-icons made by Roundicons (https://roundicons.com/) from www.flaticon.com\nOther icons made by FatCow (http://www.fatcow.com/free-icons/)
+ PCem v17\nhttps://pcem-emulator.co.uk/\n\nThis program is licensed under the GNU General Public License version 2.\nSee COPYING for more details.\n\nToolbar-icons made by Roundicons (https://roundicons.com/) from www.flaticon.com\nOther icons made by FatCow (http://www.fatcow.com/free-icons/)
-1
diff --git a/src/pc87306.c b/src/pc87306.c
index dc96d9b..91b95e0 100644
--- a/src/pc87306.c
+++ b/src/pc87306.c
@@ -200,6 +200,6 @@ void pc87306_init(uint16_t port)
pc87306_global.regs[REG_FAR] = 0x10;
pc87306_global.regs[REG_GPBA] = 0x78 >> 2;
pc87306_global.regs[REG_SCF0] = 0x30;
- pc87306_global.gpio_2 = 0xfa;
+ pc87306_global.gpio_2 = 0xff; // this is a mask only, output will be defined by zappa_brdconfig and endeavor_brdconfig in intel.c
io_sethandler(0x0078, 0x0002, pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, &pc87306_global);
}
diff --git a/src/pc87307.c b/src/pc87307.c
new file mode 100644
index 0000000..e4f8ed4
--- /dev/null
+++ b/src/pc87307.c
@@ -0,0 +1,151 @@
+#include "ibm.h"
+
+#include "fdc.h"
+#include "io.h"
+#include "lpt.h"
+#include "serial.h"
+#include "pc87307.h"
+
+typedef struct pc87307_t
+{
+ int cur_reg;
+ int cur_device;
+
+ uint8_t superio_cfg1, superio_cfg2;
+
+ struct
+ {
+ int enable;
+ uint16_t addr;
+ int irq;
+ int dma;
+ } dev[9];
+} pc87307_t;
+
+static pc87307_t pc87307_global;
+
+#define DEV_KBC 0
+#define DEV_MOUSE 1
+#define DEV_RTC 2
+#define DEV_FDC 3
+#define DEV_LPT 4
+#define DEV_COM2 5
+#define DEV_COM1 6
+#define DEV_GPIO 7
+#define DEV_POWER 8
+
+#define REG_DEVICE 0x07
+#define REG_SID 0x20
+#define REG_SUPERIO_CFG1 0x21
+#define REG_SUPERIO_CFG2 0x22
+#define REG_ENABLE 0x30
+#define REG_ADDRHI 0x60
+#define REG_ADDRLO 0x61
+#define REG_IRQ 0x70
+#define REG_DMA 0x74
+
+void pc87307_write(uint16_t port, uint8_t val, void *p)
+{
+ pc87307_t *pc87307 = (pc87307_t *)p;
+
+ if (port == 0x2e)
+ pc87307->cur_reg = val;
+ else
+ {
+ if (pc87307->cur_reg == REG_DEVICE)
+ pc87307->cur_device = val & 0xf;
+ else
+ {
+// pclog("Write pc87307 %02x [%02x] %02x\n", pc87307->cur_reg, pc87307->cur_device, val);
+ switch (pc87307->cur_reg)
+ {
+ case REG_ENABLE:
+ if (pc87307->cur_device <= DEV_POWER)
+ pc87307->dev[pc87307->cur_device].enable = val;
+ break;
+ case REG_ADDRLO:
+ if (pc87307->cur_device <= DEV_POWER)
+ pc87307->dev[pc87307->cur_device].addr = (pc87307->dev[pc87307->cur_device].addr & 0xff00) | val;
+ break;
+ case REG_ADDRHI:
+ if (pc87307->cur_device <= DEV_POWER)
+ pc87307->dev[pc87307->cur_device].addr = (pc87307->dev[pc87307->cur_device].addr & 0x00ff) | (val << 8);
+ break;
+ case REG_IRQ:
+ if (pc87307->cur_device <= DEV_POWER)
+ pc87307->dev[pc87307->cur_device].irq = val;
+ break;
+ case REG_DMA:
+ if (pc87307->cur_device <= DEV_POWER)
+ pc87307->dev[pc87307->cur_device].dma = val;
+ break;
+ }
+
+ switch (pc87307->cur_device)
+ {
+ case DEV_FDC:
+ fdc_remove();
+ if (pc87307->dev[DEV_FDC].enable & 1)
+ fdc_add();
+ break;
+ case DEV_COM1:
+ serial1_remove();
+ if (pc87307->dev[DEV_COM1].enable & 1)
+ serial1_set(pc87307->dev[DEV_COM1].addr, pc87307->dev[DEV_COM1].irq);
+ break;
+ case DEV_COM2:
+ serial2_remove();
+ if (pc87307->dev[DEV_COM2].enable & 1)
+ serial2_set(pc87307->dev[DEV_COM2].addr, pc87307->dev[DEV_COM2].irq);
+ break;
+ case DEV_LPT:
+ lpt1_remove();
+ lpt2_remove();
+ if (pc87307->dev[DEV_LPT].enable & 1)
+ lpt1_init(pc87307->dev[DEV_LPT].addr);
+ break;
+ }
+ }
+ }
+}
+
+uint8_t pc87307_read(uint16_t port, void *p)
+{
+ pc87307_t *pc87307 = (pc87307_t *)p;
+
+// pclog("Read pc87307 %02x\n", pc87307->cur_reg);
+
+ switch (pc87307->cur_reg)
+ {
+ case REG_DEVICE:
+ return pc87307->cur_device;
+ case REG_SID:
+ return 0x20; /*PC87307*/
+ case REG_SUPERIO_CFG1:
+ return pc87307->superio_cfg1;
+ case REG_SUPERIO_CFG2:
+ return pc87307->superio_cfg2;
+ case REG_ENABLE:
+ return pc87307->dev[pc87307->cur_device].enable;
+ case REG_ADDRLO:
+ return pc87307->dev[pc87307->cur_device].addr & 0xff;
+ case REG_ADDRHI:
+ return pc87307->dev[pc87307->cur_device].addr >> 8;
+ case REG_IRQ:
+ return pc87307->dev[pc87307->cur_device].irq;
+ case REG_DMA:
+ return pc87307->dev[pc87307->cur_device].dma;
+ }
+
+ return 0xff;
+}
+
+void pc87307_init(uint16_t base)
+{
+ memset(&pc87307_global, 0, sizeof(pc87307_t));
+
+ pc87307_global.superio_cfg1 = 0x04;
+ pc87307_global.superio_cfg2 = 0x03;
+
+ io_sethandler(base, 0x0002, pc87307_read, NULL, NULL, pc87307_write, NULL, NULL, &pc87307_global);
+}
diff --git a/src/pc87307.h b/src/pc87307.h
new file mode 100644
index 0000000..e28ae8a
--- /dev/null
+++ b/src/pc87307.h
@@ -0,0 +1 @@
+void pc87307_init(uint16_t addr);
diff --git a/src/pgc_palettes.h b/src/pgc_palettes.h
new file mode 100644
index 0000000..2d3d0dd
--- /dev/null
+++ b/src/pgc_palettes.h
@@ -0,0 +1,1554 @@
+/* Palette 0: Default */
+ {
+ makecol(0x00,0x00,0x00),
+ makecol(0x11,0x11,0x11),
+ makecol(0x22,0x22,0x22),
+ makecol(0x33,0x33,0x33),
+ makecol(0x44,0x44,0x44),
+ makecol(0x55,0x55,0x55),
+ makecol(0x66,0x66,0x66),
+ makecol(0x77,0x77,0x77),
+ makecol(0x88,0x88,0x88),
+ makecol(0x99,0x99,0x99),
+ makecol(0xaa,0xaa,0xaa),
+ makecol(0xbb,0xbb,0xbb),
+ makecol(0xcc,0xcc,0xcc),
+ makecol(0xdd,0xdd,0xdd),
+ makecol(0xee,0xee,0xee),
+ makecol(0xff,0xff,0xff),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x22,0x00),
+ makecol(0x00,0x44,0x00),
+ makecol(0x00,0x66,0x00),
+ makecol(0x00,0x88,0x00),
+ makecol(0x00,0xaa,0x00),
+ makecol(0x00,0xcc,0x00),
+ makecol(0x00,0xee,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x22,0xff,0x22),
+ makecol(0x44,0xff,0x44),
+ makecol(0x66,0xff,0x66),
+ makecol(0x88,0xff,0x88),
+ makecol(0xaa,0xff,0xaa),
+ makecol(0xcc,0xff,0xcc),
+ makecol(0xee,0xff,0xee),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x22,0x11),
+ makecol(0x00,0x44,0x22),
+ makecol(0x00,0x66,0x33),
+ makecol(0x00,0x88,0x44),
+ makecol(0x00,0xaa,0x55),
+ makecol(0x00,0xcc,0x66),
+ makecol(0x00,0xee,0x77),
+ makecol(0x00,0xff,0x88),
+ makecol(0x22,0xff,0x99),
+ makecol(0x44,0xff,0xaa),
+ makecol(0x66,0xff,0xbb),
+ makecol(0x88,0xff,0xcc),
+ makecol(0xaa,0xff,0xdd),
+ makecol(0xcc,0xff,0xee),
+ makecol(0xee,0xff,0xff),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x22,0x22),
+ makecol(0x00,0x44,0x44),
+ makecol(0x00,0x66,0x66),
+ makecol(0x00,0x88,0x88),
+ makecol(0x00,0xaa,0xaa),
+ makecol(0x00,0xcc,0xcc),
+ makecol(0x00,0xee,0xee),
+ makecol(0x00,0xff,0xff),
+ makecol(0x22,0xff,0xff),
+ makecol(0x44,0xff,0xff),
+ makecol(0x66,0xff,0xff),
+ makecol(0x88,0xff,0xff),
+ makecol(0xaa,0xff,0xff),
+ makecol(0xcc,0xff,0xff),
+ makecol(0xee,0xff,0xff),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x11,0x22),
+ makecol(0x00,0x22,0x44),
+ makecol(0x00,0x33,0x66),
+ makecol(0x00,0x44,0x88),
+ makecol(0x00,0x55,0xaa),
+ makecol(0x00,0x66,0xcc),
+ makecol(0x00,0x77,0xee),
+ makecol(0x00,0x88,0xff),
+ makecol(0x22,0x99,0xff),
+ makecol(0x44,0xaa,0xff),
+ makecol(0x66,0xbb,0xff),
+ makecol(0x88,0xcc,0xff),
+ makecol(0xaa,0xdd,0xff),
+ makecol(0xcc,0xee,0xff),
+ makecol(0xee,0xff,0xff),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x22),
+ makecol(0x00,0x00,0x44),
+ makecol(0x00,0x00,0x66),
+ makecol(0x00,0x00,0x88),
+ makecol(0x00,0x00,0xaa),
+ makecol(0x00,0x00,0xcc),
+ makecol(0x00,0x00,0xee),
+ makecol(0x00,0x00,0xff),
+ makecol(0x22,0x22,0xff),
+ makecol(0x44,0x44,0xff),
+ makecol(0x66,0x66,0xff),
+ makecol(0x88,0x88,0xff),
+ makecol(0xaa,0xaa,0xff),
+ makecol(0xcc,0xcc,0xff),
+ makecol(0xee,0xee,0xff),
+ makecol(0x00,0x00,0x00),
+ makecol(0x11,0x00,0x22),
+ makecol(0x22,0x00,0x44),
+ makecol(0x33,0x00,0x66),
+ makecol(0x44,0x00,0x88),
+ makecol(0x55,0x00,0xaa),
+ makecol(0x66,0x00,0xcc),
+ makecol(0x77,0x00,0xee),
+ makecol(0x88,0x00,0xff),
+ makecol(0x99,0x22,0xff),
+ makecol(0xaa,0x44,0xff),
+ makecol(0xbb,0x66,0xff),
+ makecol(0xcc,0x88,0xff),
+ makecol(0xdd,0xaa,0xff),
+ makecol(0xee,0xcc,0xff),
+ makecol(0xff,0xee,0xff),
+ makecol(0x00,0x00,0x00),
+ makecol(0x22,0x00,0x22),
+ makecol(0x44,0x00,0x44),
+ makecol(0x66,0x00,0x66),
+ makecol(0x88,0x00,0x88),
+ makecol(0xaa,0x00,0xaa),
+ makecol(0xcc,0x00,0xcc),
+ makecol(0xee,0x00,0xee),
+ makecol(0xff,0x00,0xff),
+ makecol(0xff,0x22,0xff),
+ makecol(0xff,0x44,0xff),
+ makecol(0xff,0x66,0xff),
+ makecol(0xff,0x88,0xff),
+ makecol(0xff,0xaa,0xff),
+ makecol(0xff,0xcc,0xff),
+ makecol(0xff,0xee,0xff),
+ makecol(0x00,0x00,0x00),
+ makecol(0x22,0x00,0x11),
+ makecol(0x44,0x00,0x22),
+ makecol(0x66,0x00,0x33),
+ makecol(0x88,0x00,0x44),
+ makecol(0xaa,0x00,0x55),
+ makecol(0xcc,0x00,0x66),
+ makecol(0xee,0x00,0x77),
+ makecol(0xff,0x00,0x88),
+ makecol(0xff,0x22,0x99),
+ makecol(0xff,0x44,0xaa),
+ makecol(0xff,0x66,0xbb),
+ makecol(0xff,0x88,0xcc),
+ makecol(0xff,0xaa,0xdd),
+ makecol(0xff,0xcc,0xee),
+ makecol(0xff,0xee,0xff),
+ makecol(0x00,0x00,0x00),
+ makecol(0x22,0x00,0x00),
+ makecol(0x44,0x00,0x00),
+ makecol(0x66,0x00,0x00),
+ makecol(0x88,0x00,0x00),
+ makecol(0xaa,0x00,0x00),
+ makecol(0xcc,0x00,0x00),
+ makecol(0xee,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x22,0x22),
+ makecol(0xff,0x44,0x44),
+ makecol(0xff,0x66,0x66),
+ makecol(0xff,0x88,0x88),
+ makecol(0xff,0xaa,0xaa),
+ makecol(0xff,0xcc,0xcc),
+ makecol(0xff,0xee,0xee),
+ makecol(0x00,0x00,0x00),
+ makecol(0x22,0x11,0x00),
+ makecol(0x44,0x22,0x00),
+ makecol(0x66,0x33,0x00),
+ makecol(0x88,0x44,0x00),
+ makecol(0xaa,0x55,0x00),
+ makecol(0xcc,0x66,0x00),
+ makecol(0xee,0x77,0x00),
+ makecol(0xff,0x88,0x00),
+ makecol(0xff,0x99,0x22),
+ makecol(0xff,0xaa,0x44),
+ makecol(0xff,0xbb,0x66),
+ makecol(0xff,0xcc,0x88),
+ makecol(0xff,0xdd,0xaa),
+ makecol(0xff,0xee,0xcc),
+ makecol(0xff,0xff,0xee),
+ makecol(0x00,0x00,0x00),
+ makecol(0x22,0x22,0x00),
+ makecol(0x44,0x44,0x00),
+ makecol(0x66,0x66,0x00),
+ makecol(0x88,0x88,0x00),
+ makecol(0xaa,0xaa,0x00),
+ makecol(0xcc,0xcc,0x00),
+ makecol(0xee,0xee,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x22),
+ makecol(0xff,0xff,0x44),
+ makecol(0xff,0xff,0x66),
+ makecol(0xff,0xff,0x88),
+ makecol(0xff,0xff,0xaa),
+ makecol(0xff,0xff,0xcc),
+ makecol(0xff,0xff,0xee),
+ makecol(0x00,0x00,0x00),
+ makecol(0x11,0x22,0x00),
+ makecol(0x22,0x44,0x00),
+ makecol(0x33,0x66,0x00),
+ makecol(0x44,0x88,0x00),
+ makecol(0x55,0xaa,0x00),
+ makecol(0x66,0xcc,0x00),
+ makecol(0x77,0xee,0x00),
+ makecol(0x88,0xff,0x00),
+ makecol(0x99,0xff,0x22),
+ makecol(0xaa,0xff,0x44),
+ makecol(0xbb,0xff,0x66),
+ makecol(0xcc,0xff,0x88),
+ makecol(0xdd,0xff,0xaa),
+ makecol(0xee,0xff,0xcc),
+ makecol(0xff,0xff,0xee),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x11,0x00),
+ makecol(0x11,0x33,0x11),
+ makecol(0x11,0x44,0x11),
+ makecol(0x22,0x66,0x22),
+ makecol(0x22,0x77,0x22),
+ makecol(0x33,0x99,0x33),
+ makecol(0x33,0xaa,0x33),
+ makecol(0x44,0xcc,0x44),
+ makecol(0x55,0xcc,0x55),
+ makecol(0x77,0xdd,0x77),
+ makecol(0x88,0xdd,0x88),
+ makecol(0xaa,0xee,0xaa),
+ makecol(0xbb,0xee,0xbb),
+ makecol(0xdd,0xff,0xdd),
+ makecol(0xee,0xff,0xee),
+ makecol(0x00,0x00,0x00),
+ makecol(0x11,0x00,0x00),
+ makecol(0x33,0x11,0x11),
+ makecol(0x44,0x11,0x11),
+ makecol(0x66,0x22,0x22),
+ makecol(0x77,0x22,0x22),
+ makecol(0x99,0x33,0x33),
+ makecol(0xaa,0x33,0x33),
+ makecol(0xcc,0x44,0x44),
+ makecol(0xcc,0x55,0x55),
+ makecol(0xdd,0x77,0x77),
+ makecol(0xdd,0x88,0x88),
+ makecol(0xee,0xaa,0xaa),
+ makecol(0xee,0xbb,0xbb),
+ makecol(0xff,0xdd,0xdd),
+ makecol(0xff,0xee,0xee),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x11),
+ makecol(0x11,0x11,0x33),
+ makecol(0x11,0x11,0x44),
+ makecol(0x22,0x22,0x66),
+ makecol(0x22,0x22,0x77),
+ makecol(0x33,0x33,0x99),
+ makecol(0x33,0x33,0xaa),
+ makecol(0x44,0x44,0xcc),
+ makecol(0x55,0x55,0xcc),
+ makecol(0x77,0x77,0xdd),
+ makecol(0x88,0x88,0xdd),
+ makecol(0xaa,0xaa,0xee),
+ makecol(0xbb,0xbb,0xee),
+ makecol(0xdd,0xdd,0xff),
+ makecol(0xee,0xee,0xff),
+ },
+/* Palette 1: 16-colour palette */
+ {
+ makecol(0x88,0x66,0xdd),
+ makecol(0x00,0x00,0x00),
+ makecol(0x44,0x77,0x22),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x99,0xee,0x66),
+ makecol(0x77,0x77,0x77),
+ makecol(0xff,0xff,0xff),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x44,0x77,0x22),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x77,0xaa,0x44),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x77),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x99,0xee,0x66),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0x77,0x77,0x77),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ makecol(0xff,0xff,0xff),
+ },
+/* Palette 2: 2-3-3 truecolour */
+ {
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x33),
+ makecol(0x00,0x00,0x55),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x99),
+ makecol(0x00,0x00,0xbb),
+ makecol(0x00,0x00,0xdd),
+ makecol(0x00,0x00,0xff),
+ makecol(0x33,0x00,0x00),
+ makecol(0x33,0x00,0x33),
+ makecol(0x33,0x00,0x55),
+ makecol(0x33,0x00,0x77),
+ makecol(0x33,0x00,0x99),
+ makecol(0x33,0x00,0xbb),
+ makecol(0x33,0x00,0xdd),
+ makecol(0x33,0x00,0xff),
+ makecol(0x55,0x00,0x00),
+ makecol(0x55,0x00,0x33),
+ makecol(0x55,0x00,0x55),
+ makecol(0x55,0x00,0x77),
+ makecol(0x55,0x00,0x99),
+ makecol(0x55,0x00,0xbb),
+ makecol(0x55,0x00,0xdd),
+ makecol(0x55,0x00,0xff),
+ makecol(0x77,0x00,0x00),
+ makecol(0x77,0x00,0x33),
+ makecol(0x77,0x00,0x55),
+ makecol(0x77,0x00,0x77),
+ makecol(0x77,0x00,0x99),
+ makecol(0x77,0x00,0xbb),
+ makecol(0x77,0x00,0xdd),
+ makecol(0x77,0x00,0xff),
+ makecol(0x99,0x00,0x00),
+ makecol(0x99,0x00,0x33),
+ makecol(0x99,0x00,0x55),
+ makecol(0x99,0x00,0x77),
+ makecol(0x99,0x00,0x99),
+ makecol(0x99,0x00,0xbb),
+ makecol(0x99,0x00,0xdd),
+ makecol(0x99,0x00,0xff),
+ makecol(0xbb,0x00,0x00),
+ makecol(0xbb,0x00,0x33),
+ makecol(0xbb,0x00,0x55),
+ makecol(0xbb,0x00,0x77),
+ makecol(0xbb,0x00,0x99),
+ makecol(0xbb,0x00,0xbb),
+ makecol(0xbb,0x00,0xdd),
+ makecol(0xbb,0x00,0xff),
+ makecol(0xdd,0x00,0x00),
+ makecol(0xdd,0x00,0x33),
+ makecol(0xdd,0x00,0x55),
+ makecol(0xdd,0x00,0x77),
+ makecol(0xdd,0x00,0x99),
+ makecol(0xdd,0x00,0xbb),
+ makecol(0xdd,0x00,0xdd),
+ makecol(0xdd,0x00,0xff),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x33),
+ makecol(0xff,0x00,0x55),
+ makecol(0xff,0x00,0x77),
+ makecol(0xff,0x00,0x99),
+ makecol(0xff,0x00,0xbb),
+ makecol(0xff,0x00,0xdd),
+ makecol(0xff,0x00,0xff),
+ makecol(0x00,0x55,0x00),
+ makecol(0x00,0x55,0x33),
+ makecol(0x00,0x55,0x55),
+ makecol(0x00,0x55,0x77),
+ makecol(0x00,0x55,0x99),
+ makecol(0x00,0x55,0xbb),
+ makecol(0x00,0x55,0xdd),
+ makecol(0x00,0x55,0xff),
+ makecol(0x33,0x55,0x00),
+ makecol(0x33,0x55,0x33),
+ makecol(0x33,0x55,0x55),
+ makecol(0x33,0x55,0x77),
+ makecol(0x33,0x55,0x99),
+ makecol(0x33,0x55,0xbb),
+ makecol(0x33,0x55,0xdd),
+ makecol(0x33,0x55,0xff),
+ makecol(0x55,0x55,0x00),
+ makecol(0x55,0x55,0x33),
+ makecol(0x55,0x55,0x55),
+ makecol(0x55,0x55,0x77),
+ makecol(0x55,0x55,0x99),
+ makecol(0x55,0x55,0xbb),
+ makecol(0x55,0x55,0xdd),
+ makecol(0x55,0x55,0xff),
+ makecol(0x77,0x55,0x00),
+ makecol(0x77,0x55,0x33),
+ makecol(0x77,0x55,0x55),
+ makecol(0x77,0x55,0x77),
+ makecol(0x77,0x55,0x99),
+ makecol(0x77,0x55,0xbb),
+ makecol(0x77,0x55,0xdd),
+ makecol(0x77,0x55,0xff),
+ makecol(0x99,0x55,0x00),
+ makecol(0x99,0x55,0x33),
+ makecol(0x99,0x55,0x55),
+ makecol(0x99,0x55,0x77),
+ makecol(0x99,0x55,0x99),
+ makecol(0x99,0x55,0xbb),
+ makecol(0x99,0x55,0xdd),
+ makecol(0x99,0x55,0xff),
+ makecol(0xbb,0x55,0x00),
+ makecol(0xbb,0x55,0x33),
+ makecol(0xbb,0x55,0x55),
+ makecol(0xbb,0x55,0x77),
+ makecol(0xbb,0x55,0x99),
+ makecol(0xbb,0x55,0xbb),
+ makecol(0xbb,0x55,0xdd),
+ makecol(0xbb,0x55,0xff),
+ makecol(0xdd,0x55,0x00),
+ makecol(0xdd,0x55,0x33),
+ makecol(0xdd,0x55,0x55),
+ makecol(0xdd,0x55,0x77),
+ makecol(0xdd,0x55,0x99),
+ makecol(0xdd,0x55,0xbb),
+ makecol(0xdd,0x55,0xdd),
+ makecol(0xdd,0x55,0xff),
+ makecol(0xff,0x55,0x00),
+ makecol(0xff,0x55,0x33),
+ makecol(0xff,0x55,0x55),
+ makecol(0xff,0x55,0x77),
+ makecol(0xff,0x55,0x99),
+ makecol(0xff,0x55,0xbb),
+ makecol(0xff,0x55,0xdd),
+ makecol(0xff,0x55,0xff),
+ makecol(0x00,0xaa,0x00),
+ makecol(0x00,0xaa,0x33),
+ makecol(0x00,0xaa,0x55),
+ makecol(0x00,0xaa,0x77),
+ makecol(0x00,0xaa,0x99),
+ makecol(0x00,0xaa,0xbb),
+ makecol(0x00,0xaa,0xdd),
+ makecol(0x00,0xaa,0xff),
+ makecol(0x33,0xaa,0x00),
+ makecol(0x33,0xaa,0x33),
+ makecol(0x33,0xaa,0x55),
+ makecol(0x33,0xaa,0x77),
+ makecol(0x33,0xaa,0x99),
+ makecol(0x33,0xaa,0xbb),
+ makecol(0x33,0xaa,0xdd),
+ makecol(0x33,0xaa,0xff),
+ makecol(0x55,0xaa,0x00),
+ makecol(0x55,0xaa,0x33),
+ makecol(0x55,0xaa,0x55),
+ makecol(0x55,0xaa,0x77),
+ makecol(0x55,0xaa,0x99),
+ makecol(0x55,0xaa,0xbb),
+ makecol(0x55,0xaa,0xdd),
+ makecol(0x55,0xaa,0xff),
+ makecol(0x77,0xaa,0x00),
+ makecol(0x77,0xaa,0x33),
+ makecol(0x77,0xaa,0x55),
+ makecol(0x77,0xaa,0x77),
+ makecol(0x77,0xaa,0x99),
+ makecol(0x77,0xaa,0xbb),
+ makecol(0x77,0xaa,0xdd),
+ makecol(0x77,0xaa,0xff),
+ makecol(0x99,0xaa,0x00),
+ makecol(0x99,0xaa,0x33),
+ makecol(0x99,0xaa,0x55),
+ makecol(0x99,0xaa,0x77),
+ makecol(0x99,0xaa,0x99),
+ makecol(0x99,0xaa,0xbb),
+ makecol(0x99,0xaa,0xdd),
+ makecol(0x99,0xaa,0xff),
+ makecol(0xbb,0xaa,0x00),
+ makecol(0xbb,0xaa,0x33),
+ makecol(0xbb,0xaa,0x55),
+ makecol(0xbb,0xaa,0x77),
+ makecol(0xbb,0xaa,0x99),
+ makecol(0xbb,0xaa,0xbb),
+ makecol(0xbb,0xaa,0xdd),
+ makecol(0xbb,0xaa,0xff),
+ makecol(0xdd,0xaa,0x00),
+ makecol(0xdd,0xaa,0x33),
+ makecol(0xdd,0xaa,0x55),
+ makecol(0xdd,0xaa,0x77),
+ makecol(0xdd,0xaa,0x99),
+ makecol(0xdd,0xaa,0xbb),
+ makecol(0xdd,0xaa,0xdd),
+ makecol(0xdd,0xaa,0xff),
+ makecol(0xff,0xaa,0x00),
+ makecol(0xff,0xaa,0x33),
+ makecol(0xff,0xaa,0x55),
+ makecol(0xff,0xaa,0x77),
+ makecol(0xff,0xaa,0x99),
+ makecol(0xff,0xaa,0xbb),
+ makecol(0xff,0xaa,0xdd),
+ makecol(0xff,0xaa,0xee),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x33),
+ makecol(0x00,0xff,0x55),
+ makecol(0x00,0xff,0x77),
+ makecol(0x00,0xff,0x99),
+ makecol(0x00,0xff,0xbb),
+ makecol(0x00,0xff,0xdd),
+ makecol(0x00,0xff,0xff),
+ makecol(0x33,0xff,0x00),
+ makecol(0x33,0xff,0x33),
+ makecol(0x33,0xff,0x55),
+ makecol(0x33,0xff,0x77),
+ makecol(0x33,0xff,0x99),
+ makecol(0x33,0xff,0xbb),
+ makecol(0x33,0xff,0xdd),
+ makecol(0x33,0xff,0xff),
+ makecol(0x55,0xff,0x00),
+ makecol(0x55,0xff,0x33),
+ makecol(0x55,0xff,0x55),
+ makecol(0x55,0xff,0x77),
+ makecol(0x55,0xff,0x99),
+ makecol(0x55,0xff,0xbb),
+ makecol(0x55,0xff,0xdd),
+ makecol(0x55,0xff,0xff),
+ makecol(0x77,0xff,0x00),
+ makecol(0x77,0xff,0x33),
+ makecol(0x77,0xff,0x55),
+ makecol(0x77,0xff,0x77),
+ makecol(0x77,0xff,0x99),
+ makecol(0x77,0xff,0xbb),
+ makecol(0x77,0xff,0xdd),
+ makecol(0x77,0xff,0xff),
+ makecol(0x99,0xff,0x00),
+ makecol(0x99,0xff,0x33),
+ makecol(0x99,0xff,0x55),
+ makecol(0x99,0xff,0x77),
+ makecol(0x99,0xff,0x99),
+ makecol(0x99,0xff,0xbb),
+ makecol(0x99,0xff,0xdd),
+ makecol(0x99,0xff,0xff),
+ makecol(0xbb,0xff,0x00),
+ makecol(0xbb,0xff,0x33),
+ makecol(0xbb,0xff,0x55),
+ makecol(0xbb,0xff,0x77),
+ makecol(0xbb,0xff,0x99),
+ makecol(0xbb,0xff,0xbb),
+ makecol(0xbb,0xff,0xdd),
+ makecol(0xbb,0xff,0xff),
+ makecol(0xdd,0xff,0x00),
+ makecol(0xdd,0xff,0x33),
+ makecol(0xdd,0xff,0x55),
+ makecol(0xdd,0xff,0x77),
+ makecol(0xdd,0xff,0x99),
+ makecol(0xdd,0xff,0xbb),
+ makecol(0xdd,0xff,0xdd),
+ makecol(0xdd,0xff,0xff),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x33),
+ makecol(0xff,0xff,0x55),
+ makecol(0xff,0xff,0x77),
+ makecol(0xff,0xff,0x99),
+ makecol(0xff,0xff,0xbb),
+ makecol(0xff,0xff,0xdd),
+ makecol(0xff,0xff,0xff),
+ },
+/* Palette 3: 3-2-3 truecolour */
+ {
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x33),
+ makecol(0x00,0x00,0x55),
+ makecol(0x00,0x00,0x77),
+ makecol(0x00,0x00,0x99),
+ makecol(0x00,0x00,0xbb),
+ makecol(0x00,0x00,0xdd),
+ makecol(0x00,0x00,0xff),
+ makecol(0x55,0x00,0x00),
+ makecol(0x55,0x00,0x33),
+ makecol(0x55,0x00,0x55),
+ makecol(0x55,0x00,0x77),
+ makecol(0x55,0x00,0x99),
+ makecol(0x55,0x00,0xbb),
+ makecol(0x55,0x00,0xdd),
+ makecol(0x55,0x00,0xff),
+ makecol(0xaa,0x00,0x00),
+ makecol(0xaa,0x00,0x33),
+ makecol(0xaa,0x00,0x55),
+ makecol(0xaa,0x00,0x77),
+ makecol(0xaa,0x00,0x99),
+ makecol(0xaa,0x00,0xbb),
+ makecol(0xaa,0x00,0xdd),
+ makecol(0xaa,0x00,0xff),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x33),
+ makecol(0xff,0x00,0x55),
+ makecol(0xff,0x00,0x77),
+ makecol(0xff,0x00,0x99),
+ makecol(0xff,0x00,0xbb),
+ makecol(0xff,0x00,0xdd),
+ makecol(0xff,0x00,0xff),
+ makecol(0x00,0x33,0x00),
+ makecol(0x00,0x33,0x33),
+ makecol(0x00,0x33,0x55),
+ makecol(0x00,0x33,0x77),
+ makecol(0x00,0x33,0x99),
+ makecol(0x00,0x33,0xbb),
+ makecol(0x00,0x33,0xdd),
+ makecol(0x00,0x33,0xff),
+ makecol(0x55,0x33,0x00),
+ makecol(0x55,0x33,0x33),
+ makecol(0x55,0x33,0x55),
+ makecol(0x55,0x33,0x77),
+ makecol(0x55,0x33,0x99),
+ makecol(0x55,0x33,0xbb),
+ makecol(0x55,0x33,0xdd),
+ makecol(0x55,0x33,0xff),
+ makecol(0xaa,0x33,0x00),
+ makecol(0xaa,0x33,0x33),
+ makecol(0xaa,0x33,0x55),
+ makecol(0xaa,0x33,0x77),
+ makecol(0xaa,0x33,0x99),
+ makecol(0xaa,0x33,0xbb),
+ makecol(0xaa,0x33,0xdd),
+ makecol(0xaa,0x33,0xff),
+ makecol(0xff,0x33,0x00),
+ makecol(0xff,0x33,0x33),
+ makecol(0xff,0x33,0x55),
+ makecol(0xff,0x33,0x77),
+ makecol(0xff,0x33,0x99),
+ makecol(0xff,0x33,0xbb),
+ makecol(0xff,0x33,0xdd),
+ makecol(0xff,0x33,0xff),
+ makecol(0x00,0x55,0x00),
+ makecol(0x00,0x55,0x33),
+ makecol(0x00,0x55,0x55),
+ makecol(0x00,0x55,0x77),
+ makecol(0x00,0x55,0x99),
+ makecol(0x00,0x55,0xbb),
+ makecol(0x00,0x55,0xdd),
+ makecol(0x00,0x55,0xff),
+ makecol(0x55,0x55,0x00),
+ makecol(0x55,0x55,0x33),
+ makecol(0x55,0x55,0x55),
+ makecol(0x55,0x55,0x77),
+ makecol(0x55,0x55,0x99),
+ makecol(0x55,0x55,0xbb),
+ makecol(0x55,0x55,0xdd),
+ makecol(0x55,0x55,0xff),
+ makecol(0xaa,0x55,0x00),
+ makecol(0xaa,0x55,0x33),
+ makecol(0xaa,0x55,0x55),
+ makecol(0xaa,0x55,0x77),
+ makecol(0xaa,0x55,0x99),
+ makecol(0xaa,0x55,0xbb),
+ makecol(0xaa,0x55,0xdd),
+ makecol(0xaa,0x55,0xff),
+ makecol(0xff,0x55,0x00),
+ makecol(0xff,0x55,0x33),
+ makecol(0xff,0x55,0x55),
+ makecol(0xff,0x55,0x77),
+ makecol(0xff,0x55,0x99),
+ makecol(0xff,0x55,0xbb),
+ makecol(0xff,0x55,0xdd),
+ makecol(0xff,0x55,0xff),
+ makecol(0x00,0x77,0x00),
+ makecol(0x00,0x77,0x33),
+ makecol(0x00,0x77,0x55),
+ makecol(0x00,0x77,0x77),
+ makecol(0x00,0x77,0x99),
+ makecol(0x00,0x77,0xbb),
+ makecol(0x00,0x77,0xdd),
+ makecol(0x00,0x77,0xff),
+ makecol(0x55,0x77,0x00),
+ makecol(0x55,0x77,0x33),
+ makecol(0x55,0x77,0x55),
+ makecol(0x55,0x77,0x77),
+ makecol(0x55,0x77,0x99),
+ makecol(0x55,0x77,0xbb),
+ makecol(0x55,0x77,0xdd),
+ makecol(0x55,0x77,0xff),
+ makecol(0xaa,0x77,0x00),
+ makecol(0xaa,0x77,0x33),
+ makecol(0xaa,0x77,0x55),
+ makecol(0xaa,0x77,0x77),
+ makecol(0xaa,0x77,0x99),
+ makecol(0xaa,0x77,0xbb),
+ makecol(0xaa,0x77,0xdd),
+ makecol(0xaa,0x77,0xff),
+ makecol(0xff,0x77,0x00),
+ makecol(0xff,0x77,0x33),
+ makecol(0xff,0x77,0x55),
+ makecol(0xff,0x77,0x77),
+ makecol(0xff,0x77,0x99),
+ makecol(0xff,0x77,0xbb),
+ makecol(0xff,0x77,0xdd),
+ makecol(0xff,0x77,0xff),
+ makecol(0x00,0x99,0x00),
+ makecol(0x00,0x99,0x33),
+ makecol(0x00,0x99,0x55),
+ makecol(0x00,0x99,0x77),
+ makecol(0x00,0x99,0x99),
+ makecol(0x00,0x99,0xbb),
+ makecol(0x00,0x99,0xdd),
+ makecol(0x00,0x99,0xff),
+ makecol(0x55,0x99,0x00),
+ makecol(0x55,0x99,0x33),
+ makecol(0x55,0x99,0x55),
+ makecol(0x55,0x99,0x77),
+ makecol(0x55,0x99,0x99),
+ makecol(0x55,0x99,0xbb),
+ makecol(0x55,0x99,0xdd),
+ makecol(0x55,0x99,0xff),
+ makecol(0xaa,0x99,0x00),
+ makecol(0xaa,0x99,0x33),
+ makecol(0xaa,0x99,0x55),
+ makecol(0xaa,0x99,0x77),
+ makecol(0xaa,0x99,0x99),
+ makecol(0xaa,0x99,0xbb),
+ makecol(0xaa,0x99,0xdd),
+ makecol(0xaa,0x99,0xff),
+ makecol(0xff,0x99,0x00),
+ makecol(0xff,0x99,0x33),
+ makecol(0xff,0x99,0x55),
+ makecol(0xff,0x99,0x77),
+ makecol(0xff,0x99,0x99),
+ makecol(0xff,0x99,0xbb),
+ makecol(0xff,0x99,0xdd),
+ makecol(0xff,0x99,0xff),
+ makecol(0x00,0xbb,0x00),
+ makecol(0x00,0xbb,0x33),
+ makecol(0x00,0xbb,0x55),
+ makecol(0x00,0xbb,0x77),
+ makecol(0x00,0xbb,0x99),
+ makecol(0x00,0xbb,0xbb),
+ makecol(0x00,0xbb,0xdd),
+ makecol(0x00,0xbb,0xff),
+ makecol(0x55,0xbb,0x00),
+ makecol(0x55,0xbb,0x33),
+ makecol(0x55,0xbb,0x55),
+ makecol(0x55,0xbb,0x77),
+ makecol(0x55,0xbb,0x99),
+ makecol(0x55,0xbb,0xbb),
+ makecol(0x55,0xbb,0xdd),
+ makecol(0x55,0xbb,0xff),
+ makecol(0xaa,0xbb,0x00),
+ makecol(0xaa,0xbb,0x33),
+ makecol(0xaa,0xbb,0x55),
+ makecol(0xaa,0xbb,0x77),
+ makecol(0xaa,0xbb,0x99),
+ makecol(0xaa,0xbb,0xbb),
+ makecol(0xaa,0xbb,0xdd),
+ makecol(0xaa,0xbb,0xff),
+ makecol(0xff,0xbb,0x00),
+ makecol(0xff,0xbb,0x33),
+ makecol(0xff,0xbb,0x55),
+ makecol(0xff,0xbb,0x77),
+ makecol(0xff,0xbb,0x99),
+ makecol(0xff,0xbb,0xbb),
+ makecol(0xff,0xbb,0xdd),
+ makecol(0xff,0xbb,0xff),
+ makecol(0x00,0xdd,0x00),
+ makecol(0x00,0xdd,0x33),
+ makecol(0x00,0xdd,0x55),
+ makecol(0x00,0xdd,0x77),
+ makecol(0x00,0xdd,0x99),
+ makecol(0x00,0xdd,0xbb),
+ makecol(0x00,0xdd,0xdd),
+ makecol(0x00,0xdd,0xff),
+ makecol(0x55,0xdd,0x00),
+ makecol(0x55,0xdd,0x33),
+ makecol(0x55,0xdd,0x55),
+ makecol(0x55,0xdd,0x77),
+ makecol(0x55,0xdd,0x99),
+ makecol(0x55,0xdd,0xbb),
+ makecol(0x55,0xdd,0xdd),
+ makecol(0x55,0xdd,0xff),
+ makecol(0xaa,0xdd,0x00),
+ makecol(0xaa,0xdd,0x33),
+ makecol(0xaa,0xdd,0x55),
+ makecol(0xaa,0xdd,0x77),
+ makecol(0xaa,0xdd,0x99),
+ makecol(0xaa,0xdd,0xbb),
+ makecol(0xaa,0xdd,0xdd),
+ makecol(0xaa,0xdd,0xff),
+ makecol(0xff,0xdd,0x00),
+ makecol(0xff,0xdd,0x33),
+ makecol(0xff,0xdd,0x55),
+ makecol(0xff,0xdd,0x77),
+ makecol(0xff,0xdd,0x99),
+ makecol(0xff,0xdd,0xbb),
+ makecol(0xff,0xdd,0xdd),
+ makecol(0xff,0xdd,0xff),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x33),
+ makecol(0x00,0xff,0x55),
+ makecol(0x00,0xff,0x77),
+ makecol(0x00,0xff,0x99),
+ makecol(0x00,0xff,0xbb),
+ makecol(0x00,0xff,0xdd),
+ makecol(0x00,0xff,0xff),
+ makecol(0x55,0xff,0x00),
+ makecol(0x55,0xff,0x33),
+ makecol(0x55,0xff,0x55),
+ makecol(0x55,0xff,0x77),
+ makecol(0x55,0xff,0x99),
+ makecol(0x55,0xff,0xbb),
+ makecol(0x55,0xff,0xdd),
+ makecol(0x55,0xff,0xff),
+ makecol(0xaa,0xff,0x00),
+ makecol(0xaa,0xff,0x33),
+ makecol(0xaa,0xff,0x55),
+ makecol(0xaa,0xff,0x77),
+ makecol(0xaa,0xff,0x99),
+ makecol(0xaa,0xff,0xbb),
+ makecol(0xaa,0xff,0xdd),
+ makecol(0xaa,0xff,0xff),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x33),
+ makecol(0xff,0xff,0x55),
+ makecol(0xff,0xff,0x77),
+ makecol(0xff,0xff,0x99),
+ makecol(0xff,0xff,0xbb),
+ makecol(0xff,0xff,0xdd),
+ makecol(0xff,0xff,0xff),
+ },
+/* Palette 4: 3-3-2 truecolour */
+ {
+ makecol(0x00, 0x00, 0x00),
+ makecol(0x00, 0x00, 0x55),
+ makecol(0x00, 0x00, 0xaa),
+ makecol(0x00, 0x00, 0xff),
+ makecol(0x00, 0x33, 0x00),
+ makecol(0x00, 0x33, 0x55),
+ makecol(0x00, 0x33, 0xaa),
+ makecol(0x00, 0x33, 0xff),
+ makecol(0x00, 0x55, 0x00),
+ makecol(0x00, 0x55, 0x55),
+ makecol(0x00, 0x55, 0xaa),
+ makecol(0x00, 0x55, 0xff),
+ makecol(0x00, 0x77, 0x00),
+ makecol(0x00, 0x77, 0x55),
+ makecol(0x00, 0x77, 0xaa),
+ makecol(0x00, 0x77, 0xff),
+ makecol(0x00, 0x99, 0x00),
+ makecol(0x00, 0x99, 0x55),
+ makecol(0x00, 0x99, 0xaa),
+ makecol(0x00, 0x99, 0xff),
+ makecol(0x00, 0xbb, 0x00),
+ makecol(0x00, 0xbb, 0x55),
+ makecol(0x00, 0xbb, 0xaa),
+ makecol(0x00, 0xbb, 0xff),
+ makecol(0x00, 0xdd, 0x00),
+ makecol(0x00, 0xdd, 0x55),
+ makecol(0x00, 0xdd, 0xaa),
+ makecol(0x00, 0xdd, 0xff),
+ makecol(0x00, 0xff, 0x00),
+ makecol(0x00, 0xff, 0x55),
+ makecol(0x00, 0xff, 0xaa),
+ makecol(0x00, 0xff, 0xff),
+ makecol(0x33, 0x00, 0x00),
+ makecol(0x33, 0x00, 0x55),
+ makecol(0x33, 0x00, 0xaa),
+ makecol(0x33, 0x00, 0xff),
+ makecol(0x33, 0x33, 0x00),
+ makecol(0x33, 0x33, 0x55),
+ makecol(0x33, 0x33, 0xaa),
+ makecol(0x33, 0x33, 0xff),
+ makecol(0x33, 0x55, 0x00),
+ makecol(0x33, 0x55, 0x55),
+ makecol(0x33, 0x55, 0xaa),
+ makecol(0x33, 0x55, 0xff),
+ makecol(0x33, 0x77, 0x00),
+ makecol(0x33, 0x77, 0x55),
+ makecol(0x33, 0x77, 0xaa),
+ makecol(0x33, 0x77, 0xff),
+ makecol(0x33, 0x99, 0x00),
+ makecol(0x33, 0x99, 0x55),
+ makecol(0x33, 0x99, 0xaa),
+ makecol(0x33, 0x99, 0xff),
+ makecol(0x33, 0xbb, 0x00),
+ makecol(0x33, 0xbb, 0x55),
+ makecol(0x33, 0xbb, 0xaa),
+ makecol(0x33, 0xbb, 0xff),
+ makecol(0x33, 0xdd, 0x00),
+ makecol(0x33, 0xdd, 0x55),
+ makecol(0x33, 0xdd, 0xaa),
+ makecol(0x33, 0xdd, 0xff),
+ makecol(0x33, 0xff, 0x00),
+ makecol(0x33, 0xff, 0x55),
+ makecol(0x33, 0xff, 0xaa),
+ makecol(0x33, 0xff, 0xff),
+ makecol(0x55, 0x00, 0x00),
+ makecol(0x55, 0x00, 0x55),
+ makecol(0x55, 0x00, 0xaa),
+ makecol(0x55, 0x00, 0xff),
+ makecol(0x55, 0x33, 0x00),
+ makecol(0x55, 0x33, 0x55),
+ makecol(0x55, 0x33, 0xaa),
+ makecol(0x55, 0x33, 0xff),
+ makecol(0x55, 0x55, 0x00),
+ makecol(0x55, 0x55, 0x55),
+ makecol(0x55, 0x55, 0xaa),
+ makecol(0x55, 0x55, 0xff),
+ makecol(0x55, 0x77, 0x00),
+ makecol(0x55, 0x77, 0x55),
+ makecol(0x55, 0x77, 0xaa),
+ makecol(0x55, 0x77, 0xff),
+ makecol(0x55, 0x99, 0x00),
+ makecol(0x55, 0x99, 0x55),
+ makecol(0x55, 0x99, 0xaa),
+ makecol(0x55, 0x99, 0xff),
+ makecol(0x55, 0xbb, 0x00),
+ makecol(0x55, 0xbb, 0x55),
+ makecol(0x55, 0xbb, 0xaa),
+ makecol(0x55, 0xbb, 0xff),
+ makecol(0x55, 0xdd, 0x00),
+ makecol(0x55, 0xdd, 0x55),
+ makecol(0x55, 0xdd, 0xaa),
+ makecol(0x55, 0xdd, 0xff),
+ makecol(0x55, 0xff, 0x00),
+ makecol(0x55, 0xff, 0x55),
+ makecol(0x55, 0xff, 0xaa),
+ makecol(0x55, 0xff, 0xff),
+ makecol(0x77, 0x00, 0x00),
+ makecol(0x77, 0x00, 0x55),
+ makecol(0x77, 0x00, 0xaa),
+ makecol(0x77, 0x00, 0xff),
+ makecol(0x77, 0x33, 0x00),
+ makecol(0x77, 0x33, 0x55),
+ makecol(0x77, 0x33, 0xaa),
+ makecol(0x77, 0x33, 0xff),
+ makecol(0x77, 0x55, 0x00),
+ makecol(0x77, 0x55, 0x55),
+ makecol(0x77, 0x55, 0xaa),
+ makecol(0x77, 0x55, 0xff),
+ makecol(0x77, 0x77, 0x00),
+ makecol(0x77, 0x77, 0x55),
+ makecol(0x77, 0x77, 0xaa),
+ makecol(0x77, 0x77, 0xff),
+ makecol(0x77, 0x99, 0x00),
+ makecol(0x77, 0x99, 0x55),
+ makecol(0x77, 0x99, 0xaa),
+ makecol(0x77, 0x99, 0xff),
+ makecol(0x77, 0xbb, 0x00),
+ makecol(0x77, 0xbb, 0x55),
+ makecol(0x77, 0xbb, 0xaa),
+ makecol(0x77, 0xbb, 0xff),
+ makecol(0x77, 0xdd, 0x00),
+ makecol(0x77, 0xdd, 0x55),
+ makecol(0x77, 0xdd, 0xaa),
+ makecol(0x77, 0xdd, 0xff),
+ makecol(0x77, 0xff, 0x00),
+ makecol(0x77, 0xff, 0x55),
+ makecol(0x77, 0xff, 0xaa),
+ makecol(0x77, 0xff, 0xff),
+ makecol(0x99, 0x00, 0x00),
+ makecol(0x99, 0x00, 0x55),
+ makecol(0x99, 0x00, 0xaa),
+ makecol(0x99, 0x00, 0xff),
+ makecol(0x99, 0x33, 0x00),
+ makecol(0x99, 0x33, 0x55),
+ makecol(0x99, 0x33, 0xaa),
+ makecol(0x99, 0x33, 0xff),
+ makecol(0x99, 0x55, 0x00),
+ makecol(0x99, 0x55, 0x55),
+ makecol(0x99, 0x55, 0xaa),
+ makecol(0x99, 0x55, 0xff),
+ makecol(0x99, 0x77, 0x00),
+ makecol(0x99, 0x77, 0x55),
+ makecol(0x99, 0x77, 0xaa),
+ makecol(0x99, 0x77, 0xff),
+ makecol(0x99, 0x99, 0x00),
+ makecol(0x99, 0x99, 0x55),
+ makecol(0x99, 0x99, 0xaa),
+ makecol(0x99, 0x99, 0xff),
+ makecol(0x99, 0xbb, 0x00),
+ makecol(0x99, 0xbb, 0x55),
+ makecol(0x99, 0xbb, 0xaa),
+ makecol(0x99, 0xbb, 0xff),
+ makecol(0x99, 0xdd, 0x00),
+ makecol(0x99, 0xdd, 0x55),
+ makecol(0x99, 0xdd, 0xaa),
+ makecol(0x99, 0xdd, 0xff),
+ makecol(0x99, 0xff, 0x00),
+ makecol(0x99, 0xff, 0x55),
+ makecol(0x99, 0xff, 0xaa),
+ makecol(0x99, 0xff, 0xff),
+ makecol(0xbb, 0x00, 0x00),
+ makecol(0xbb, 0x00, 0x55),
+ makecol(0xbb, 0x00, 0xaa),
+ makecol(0xbb, 0x00, 0xff),
+ makecol(0xbb, 0x33, 0x00),
+ makecol(0xbb, 0x33, 0x55),
+ makecol(0xbb, 0x33, 0xaa),
+ makecol(0xbb, 0x33, 0xff),
+ makecol(0xbb, 0x55, 0x00),
+ makecol(0xbb, 0x55, 0x55),
+ makecol(0xbb, 0x55, 0xaa),
+ makecol(0xbb, 0x55, 0xff),
+ makecol(0xbb, 0x77, 0x00),
+ makecol(0xbb, 0x77, 0x55),
+ makecol(0xbb, 0x77, 0xaa),
+ makecol(0xbb, 0x77, 0xff),
+ makecol(0xbb, 0x99, 0x00),
+ makecol(0xbb, 0x99, 0x55),
+ makecol(0xbb, 0x99, 0xaa),
+ makecol(0xbb, 0x99, 0xff),
+ makecol(0xbb, 0xbb, 0x00),
+ makecol(0xbb, 0xbb, 0x55),
+ makecol(0xbb, 0xbb, 0xaa),
+ makecol(0xbb, 0xbb, 0xff),
+ makecol(0xbb, 0xdd, 0x00),
+ makecol(0xbb, 0xdd, 0x55),
+ makecol(0xbb, 0xdd, 0xaa),
+ makecol(0xbb, 0xdd, 0xff),
+ makecol(0xbb, 0xff, 0x00),
+ makecol(0xbb, 0xff, 0x55),
+ makecol(0xbb, 0xff, 0xaa),
+ makecol(0xbb, 0xff, 0xff),
+ makecol(0xdd, 0x00, 0x00),
+ makecol(0xdd, 0x00, 0x55),
+ makecol(0xdd, 0x00, 0xaa),
+ makecol(0xdd, 0x00, 0xff),
+ makecol(0xdd, 0x33, 0x00),
+ makecol(0xdd, 0x33, 0x55),
+ makecol(0xdd, 0x33, 0xaa),
+ makecol(0xdd, 0x33, 0xff),
+ makecol(0xdd, 0x55, 0x00),
+ makecol(0xdd, 0x55, 0x55),
+ makecol(0xdd, 0x55, 0xaa),
+ makecol(0xdd, 0x55, 0xff),
+ makecol(0xdd, 0x77, 0x00),
+ makecol(0xdd, 0x77, 0x55),
+ makecol(0xdd, 0x77, 0xaa),
+ makecol(0xdd, 0x77, 0xff),
+ makecol(0xdd, 0x99, 0x00),
+ makecol(0xdd, 0x99, 0x55),
+ makecol(0xdd, 0x99, 0xaa),
+ makecol(0xdd, 0x99, 0xff),
+ makecol(0xdd, 0xbb, 0x00),
+ makecol(0xdd, 0xbb, 0x55),
+ makecol(0xdd, 0xbb, 0xaa),
+ makecol(0xdd, 0xbb, 0xff),
+ makecol(0xdd, 0xdd, 0x00),
+ makecol(0xdd, 0xdd, 0x55),
+ makecol(0xdd, 0xdd, 0xaa),
+ makecol(0xdd, 0xdd, 0xff),
+ makecol(0xdd, 0xff, 0x00),
+ makecol(0xdd, 0xff, 0x55),
+ makecol(0xdd, 0xff, 0xaa),
+ makecol(0xdd, 0xff, 0xff),
+ makecol(0xff, 0x00, 0x00),
+ makecol(0xff, 0x00, 0x55),
+ makecol(0xff, 0x00, 0xaa),
+ makecol(0xff, 0x00, 0xff),
+ makecol(0xff, 0x33, 0x00),
+ makecol(0xff, 0x33, 0x55),
+ makecol(0xff, 0x33, 0xaa),
+ makecol(0xff, 0x33, 0xff),
+ makecol(0xff, 0x55, 0x00),
+ makecol(0xff, 0x55, 0x55),
+ makecol(0xff, 0x55, 0xaa),
+ makecol(0xff, 0x55, 0xff),
+ makecol(0xff, 0x77, 0x00),
+ makecol(0xff, 0x77, 0x55),
+ makecol(0xff, 0x77, 0xaa),
+ makecol(0xff, 0x77, 0xff),
+ makecol(0xff, 0x99, 0x00),
+ makecol(0xff, 0x99, 0x55),
+ makecol(0xff, 0x99, 0xaa),
+ makecol(0xff, 0x99, 0xff),
+ makecol(0xff, 0xbb, 0x00),
+ makecol(0xff, 0xbb, 0x55),
+ makecol(0xff, 0xbb, 0xaa),
+ makecol(0xff, 0xbb, 0xff),
+ makecol(0xff, 0xdd, 0x00),
+ makecol(0xff, 0xdd, 0x55),
+ makecol(0xff, 0xdd, 0xaa),
+ makecol(0xff, 0xdd, 0xff),
+ makecol(0xff, 0xff, 0x00),
+ makecol(0xff, 0xff, 0x55),
+ makecol(0xff, 0xff, 0xaa),
+ makecol(0xff, 0xff, 0xff),
+ },
+/* Palette 5: 6x6x6 colour cube */
+ {
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x33),
+ makecol(0x00,0x00,0x66),
+ makecol(0x00,0x00,0x99),
+ makecol(0x00,0x00,0xcc),
+ makecol(0x00,0x00,0xff),
+ makecol(0x33,0x00,0x00),
+ makecol(0x33,0x00,0x33),
+ makecol(0x33,0x00,0x66),
+ makecol(0x33,0x00,0x99),
+ makecol(0x33,0x00,0xcc),
+ makecol(0x33,0x00,0xff),
+ makecol(0x66,0x00,0x00),
+ makecol(0x66,0x00,0x33),
+ makecol(0x66,0x00,0x66),
+ makecol(0x66,0x00,0x99),
+ makecol(0x66,0x00,0xcc),
+ makecol(0x66,0x00,0xff),
+ makecol(0x99,0x00,0x00),
+ makecol(0x99,0x00,0x33),
+ makecol(0x99,0x00,0x66),
+ makecol(0x99,0x00,0x99),
+ makecol(0x99,0x00,0xcc),
+ makecol(0x99,0x00,0xff),
+ makecol(0xcc,0x00,0x00),
+ makecol(0xcc,0x00,0x33),
+ makecol(0xcc,0x00,0x66),
+ makecol(0xcc,0x00,0x99),
+ makecol(0xcc,0x00,0xcc),
+ makecol(0xcc,0x00,0xff),
+ makecol(0xff,0x00,0x00),
+ makecol(0xff,0x00,0x33),
+ makecol(0xff,0x00,0x66),
+ makecol(0xff,0x00,0x99),
+ makecol(0xff,0x00,0xcc),
+ makecol(0xff,0x00,0xff),
+ makecol(0x00,0x33,0x00),
+ makecol(0x00,0x33,0x33),
+ makecol(0x00,0x33,0x66),
+ makecol(0x00,0x33,0x99),
+ makecol(0x00,0x33,0xcc),
+ makecol(0x00,0x33,0xff),
+ makecol(0x33,0x33,0x00),
+ makecol(0x33,0x33,0x33),
+ makecol(0x33,0x33,0x66),
+ makecol(0x33,0x33,0x99),
+ makecol(0x33,0x33,0xcc),
+ makecol(0x33,0x33,0xff),
+ makecol(0x66,0x33,0x00),
+ makecol(0x66,0x33,0x33),
+ makecol(0x66,0x33,0x66),
+ makecol(0x66,0x33,0x99),
+ makecol(0x66,0x33,0xcc),
+ makecol(0x66,0x33,0xff),
+ makecol(0x99,0x33,0x00),
+ makecol(0x99,0x33,0x33),
+ makecol(0x99,0x33,0x66),
+ makecol(0x99,0x33,0x99),
+ makecol(0x99,0x33,0xcc),
+ makecol(0x99,0x33,0xff),
+ makecol(0xcc,0x33,0x00),
+ makecol(0xcc,0x33,0x33),
+ makecol(0xcc,0x33,0x66),
+ makecol(0xcc,0x33,0x99),
+ makecol(0xcc,0x33,0xcc),
+ makecol(0xcc,0x33,0xff),
+ makecol(0xff,0x33,0x00),
+ makecol(0xff,0x33,0x33),
+ makecol(0xff,0x33,0x66),
+ makecol(0xff,0x33,0x99),
+ makecol(0xff,0x33,0xcc),
+ makecol(0xff,0x33,0xff),
+ makecol(0x00,0x66,0x00),
+ makecol(0x00,0x66,0x33),
+ makecol(0x00,0x66,0x66),
+ makecol(0x00,0x66,0x99),
+ makecol(0x00,0x66,0xcc),
+ makecol(0x00,0x66,0xff),
+ makecol(0x33,0x66,0x00),
+ makecol(0x33,0x66,0x33),
+ makecol(0x33,0x66,0x66),
+ makecol(0x33,0x66,0x99),
+ makecol(0x33,0x66,0xcc),
+ makecol(0x33,0x66,0xff),
+ makecol(0x66,0x66,0x00),
+ makecol(0x66,0x66,0x33),
+ makecol(0x66,0x66,0x66),
+ makecol(0x66,0x66,0x99),
+ makecol(0x66,0x66,0xcc),
+ makecol(0x66,0x66,0xff),
+ makecol(0x99,0x66,0x00),
+ makecol(0x99,0x66,0x33),
+ makecol(0x99,0x66,0x66),
+ makecol(0x99,0x66,0x99),
+ makecol(0x99,0x66,0xcc),
+ makecol(0x99,0x66,0xff),
+ makecol(0xcc,0x66,0x00),
+ makecol(0xcc,0x66,0x33),
+ makecol(0xcc,0x66,0x66),
+ makecol(0xcc,0x66,0x99),
+ makecol(0xcc,0x66,0xcc),
+ makecol(0xcc,0x66,0xff),
+ makecol(0xff,0x66,0x00),
+ makecol(0xff,0x66,0x33),
+ makecol(0xff,0x66,0x66),
+ makecol(0xff,0x66,0x99),
+ makecol(0xff,0x66,0xcc),
+ makecol(0xff,0x66,0xff),
+ makecol(0x00,0x99,0x00),
+ makecol(0x00,0x99,0x33),
+ makecol(0x00,0x99,0x66),
+ makecol(0x00,0x99,0x99),
+ makecol(0x00,0x99,0xcc),
+ makecol(0x00,0x99,0xff),
+ makecol(0x33,0x99,0x00),
+ makecol(0x33,0x99,0x33),
+ makecol(0x33,0x99,0x66),
+ makecol(0x33,0x99,0x99),
+ makecol(0x33,0x99,0xcc),
+ makecol(0x33,0x99,0xff),
+ makecol(0x66,0x99,0x00),
+ makecol(0x66,0x99,0x33),
+ makecol(0x66,0x99,0x66),
+ makecol(0x66,0x99,0x99),
+ makecol(0x66,0x99,0xcc),
+ makecol(0x66,0x99,0xff),
+ makecol(0x99,0x99,0x00),
+ makecol(0x99,0x99,0x33),
+ makecol(0x99,0x99,0x66),
+ makecol(0x99,0x99,0x99),
+ makecol(0x99,0x99,0xcc),
+ makecol(0x99,0x99,0xff),
+ makecol(0xcc,0x99,0x00),
+ makecol(0xcc,0x99,0x33),
+ makecol(0xcc,0x99,0x66),
+ makecol(0xcc,0x99,0x99),
+ makecol(0xcc,0x99,0xcc),
+ makecol(0xcc,0x99,0xff),
+ makecol(0xff,0x99,0x00),
+ makecol(0xff,0x99,0x33),
+ makecol(0xff,0x99,0x66),
+ makecol(0xff,0x99,0x99),
+ makecol(0xff,0x99,0xcc),
+ makecol(0xff,0x99,0xff),
+ makecol(0x00,0xcc,0x00),
+ makecol(0x00,0xcc,0x33),
+ makecol(0x00,0xcc,0x66),
+ makecol(0x00,0xcc,0x99),
+ makecol(0x00,0xcc,0xcc),
+ makecol(0x00,0xcc,0xff),
+ makecol(0x33,0xcc,0x00),
+ makecol(0x33,0xcc,0x33),
+ makecol(0x33,0xcc,0x66),
+ makecol(0x33,0xcc,0x99),
+ makecol(0x33,0xcc,0xcc),
+ makecol(0x33,0xcc,0xff),
+ makecol(0x66,0xcc,0x00),
+ makecol(0x66,0xcc,0x33),
+ makecol(0x66,0xcc,0x66),
+ makecol(0x66,0xcc,0x99),
+ makecol(0x66,0xcc,0xcc),
+ makecol(0x66,0xcc,0xff),
+ makecol(0x99,0xcc,0x00),
+ makecol(0x99,0xcc,0x33),
+ makecol(0x99,0xcc,0x66),
+ makecol(0x99,0xcc,0x99),
+ makecol(0x99,0xcc,0xcc),
+ makecol(0x99,0xcc,0xff),
+ makecol(0xcc,0xcc,0x00),
+ makecol(0xcc,0xcc,0x33),
+ makecol(0xcc,0xcc,0x66),
+ makecol(0xcc,0xcc,0x99),
+ makecol(0xcc,0xcc,0xcc),
+ makecol(0xcc,0xcc,0xff),
+ makecol(0xff,0xcc,0x00),
+ makecol(0xff,0xcc,0x33),
+ makecol(0xff,0xcc,0x66),
+ makecol(0xff,0xcc,0x99),
+ makecol(0xff,0xcc,0xcc),
+ makecol(0xff,0xcc,0xff),
+ makecol(0x00,0xff,0x00),
+ makecol(0x00,0xff,0x33),
+ makecol(0x00,0xff,0x66),
+ makecol(0x00,0xff,0x99),
+ makecol(0x00,0xff,0xcc),
+ makecol(0x00,0xff,0xff),
+ makecol(0x33,0xff,0x00),
+ makecol(0x33,0xff,0x33),
+ makecol(0x33,0xff,0x66),
+ makecol(0x33,0xff,0x99),
+ makecol(0x33,0xff,0xcc),
+ makecol(0x33,0xff,0xff),
+ makecol(0x66,0xff,0x00),
+ makecol(0x66,0xff,0x33),
+ makecol(0x66,0xff,0x66),
+ makecol(0x66,0xff,0x99),
+ makecol(0x66,0xff,0xcc),
+ makecol(0x66,0xff,0xff),
+ makecol(0x99,0xff,0x00),
+ makecol(0x99,0xff,0x33),
+ makecol(0x99,0xff,0x66),
+ makecol(0x99,0xff,0x99),
+ makecol(0x99,0xff,0xcc),
+ makecol(0x99,0xff,0xff),
+ makecol(0xcc,0xff,0x00),
+ makecol(0xcc,0xff,0x33),
+ makecol(0xcc,0xff,0x66),
+ makecol(0xcc,0xff,0x99),
+ makecol(0xcc,0xff,0xcc),
+ makecol(0xcc,0xff,0xff),
+ makecol(0xff,0xff,0x00),
+ makecol(0xff,0xff,0x33),
+ makecol(0xff,0xff,0x66),
+ makecol(0xff,0xff,0x99),
+ makecol(0xff,0xff,0xcc),
+ makecol(0xff,0xff,0xff),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ makecol(0x00,0x00,0x00),
+ },
diff --git a/src/pic.c b/src/pic.c
index a7636ef..c93def6 100644
--- a/src/pic.c
+++ b/src/pic.c
@@ -10,13 +10,19 @@ int pic_intpending;
void pic_updatepending()
{
- if ((pic2.pend&~pic2.mask)&~pic2.mask2)
- pic.pend |= (1 << 2);
+ if (AT || romset == ROM_XI8088)
+ {
+ if ((pic2.pend&~pic2.mask)&~pic2.mask2)
+ pic.pend |= (1 << 2);
+ else
+ pic.pend &= ~(1 << 2);
+ pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2;
+ if (!((pic.mask | pic.mask2) & (1 << 2)))
+ pic_intpending |= ((pic2.pend&~pic2.mask)&~pic2.mask2);
+ }
else
- pic.pend &= ~(1 << 2);
- pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2;
- if (!((pic.mask | pic.mask2) & (1 << 2)))
- pic_intpending |= ((pic2.pend&~pic2.mask)&~pic2.mask2);
+ pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2;
+
/* pclog("pic_intpending = %i %02X %02X %02X %02X\n", pic_intpending, pic.ins, pic.pend, pic.mask, pic.mask2);
pclog(" %02X %02X %02X %02X %i %i\n", pic2.ins, pic2.pend, pic2.mask, pic2.mask2, ((pic.mask | pic.mask2) & (1 << 2)), ((pic2.pend&~pic2.mask)&~pic2.mask2));*/
}
@@ -64,7 +70,7 @@ static void pic_autoeoi()
pic.ins&=~(1<0xFF)
+ if ((AT || romset == ROM_XI8088) && num>0xFF)
{
pic2.pend|=(num>>8);
if ((pic2.pend&~pic2.mask)&~pic2.mask2)
pic.pend |= (1 << 2);
}
- else
+ else if (num <= 0xff)
{
pic.pend|=num;
}
@@ -345,7 +350,7 @@ void picintlevel(uint16_t num)
{
int c = 0;
while (!(num & (1 << c))) c++;
- if (AT && c == 2)
+ if ((AT || romset == ROM_XI8088) && num == (1 << 2))
{
c = 9;
num = 1 << 9;
@@ -371,7 +376,7 @@ void picintc(uint16_t num)
if (!num)
return;
while (!(num & (1 << c))) c++;
- if (AT && c == 2)
+ if ((AT || romset == ROM_XI8088) && num == (1 << 2))
{
c = 9;
num = 1 << 9;
@@ -379,13 +384,13 @@ void picintc(uint16_t num)
// pclog("INTC %04X %i\n", num, c);
pic_current[c]=0;
- if (num > 0xff)
+ if ((AT || romset == ROM_XI8088) && num > 0xff)
{
pic2.pend &= ~(num >> 8);
if (!((pic2.pend&~pic2.mask)&~pic2.mask2))
pic.pend &= ~(1 << 2);
}
- else
+ else if(num <= 0xff)
{
pic.pend&=~num;
}
@@ -396,54 +401,35 @@ uint8_t picinterrupt()
{
uint8_t temp=pic.pend&~pic.mask;
int c;
- for (c = 0; c < 2; c++)
+ for (c = 0; c < 8; c++)
{
- if (temp & (1 << c))
+ if ((AT || romset == ROM_XI8088) && (temp & (1 << 2)))
{
- if (!(pic.level_sensitive & (1 << c)))
- pic.pend &= ~(1 << c);
- pic.ins |= (1 << c);
- pic_update_mask(&pic.mask2, pic.ins);
-
- pic_updatepending();
- if (!c)
- pit_set_gate(&pit2, 0, 0);
-
- if (pic.icw4 & 0x02)
- pic_autoeoi();
-
- return c+pic.vector;
- }
- }
- if (temp & (1 << 2))
- {
- uint8_t temp2 = pic2.pend & ~pic2.mask;
- for (c = 0; c < 8; c++)
- {
- if (temp2 & (1 << c))
+ uint8_t temp2 = pic2.pend & ~pic2.mask;
+ for (c = 0; c < 8; c++)
{
- if (!(pic2.level_sensitive & (1 << c)))
- pic2.pend &= ~(1 << c);
- pic2.ins |= (1 << c);
- pic_update_mask(&pic2.mask2, pic2.ins);
+ if (temp2 & (1 << c))
+ {
+ if (!(pic2.level_sensitive & (1 << c)))
+ pic2.pend &= ~(1 << c);
+ pic2.ins |= (1 << c);
+ pic_update_mask(&pic2.mask2, pic2.ins);
- if (!(pic2.level_sensitive & (1 << c)))
- pic.pend &= ~(1 << c);
- pic.ins |= (1 << 2); /*Cascade IRQ*/
- pic_update_mask(&pic.mask2, pic.ins);
+ if (!(pic2.level_sensitive & (1 << c)))
+ pic.pend &= ~(1 << c);
+ pic.ins |= (1 << 2); /*Cascade IRQ*/
+ pic_update_mask(&pic.mask2, pic.ins);
- pic_updatepending();
+ pic_updatepending();
- if (pic2.icw4 & 0x02)
- pic2_autoeoi();
+ if (pic2.icw4 & 0x02)
+ pic2_autoeoi();
- return c+pic2.vector;
+ return c+pic2.vector;
+ }
}
}
- }
- for (c = 3; c < 8; c++)
- {
- if (temp & (1 << c))
+ else if (temp & (1 << c))
{
if (!(pic.level_sensitive & (1 << c)))
pic.pend &= ~(1 << c);
@@ -453,7 +439,6 @@ uint8_t picinterrupt()
if (pic.icw4 & 0x02)
pic_autoeoi();
-
return c+pic.vector;
}
}
diff --git a/src/piix.c b/src/piix.c
index 73676cf..4e76b26 100644
--- a/src/piix.c
+++ b/src/piix.c
@@ -8,20 +8,40 @@
#include "ibm.h"
#include "ide.h"
#include "ide_sff8038i.h"
+#include "keyboard_at.h"
#include "io.h"
#include "mem.h"
#include "pci.h"
#include "pic.h"
-
#include "piix.h"
+#include "piix_pm.h"
+enum
+{
+ TYPE_PIIX = 0,
+ TYPE_PIIX3,
+ TYPE_PIIX4
+};
+
+static piix_t piix;
static uint8_t card_piix[256], card_piix_ide[256];
static sff_busmaster_t piix_busmaster[2];
+static uint8_t piix_rc = 0;
+static void (*piix_nb_reset)();
+
+#define REG_SMICNTL 0xa0
+#define REG_SMIEN 0xa2
+#define REG_SMIREQ 0xaa
+
+#define SMICNTL_CSMIGATE (1 << 0)
+#define SMIEN_APMC (1 << 7)
+#define SMIREQ_RAPMC (1 << 7)
+
void piix_write(int func, int addr, uint8_t val, void *priv)
{
// pclog("piix_write: func=%d addr=%02x val=%02x %04x:%08x\n", func, addr, val, CS, pc);
- if (func > 1)
+ if (func > ((piix.type == TYPE_PIIX4) ? 3 : 1))
return;
if (func == 1) /*IDE*/
@@ -79,6 +99,14 @@ void piix_write(int func, int addr, uint8_t val, void *priv)
}
// pclog("PIIX write %02X %02X\n", addr, val);
}
+ else if (func == 2) /*USB*/
+ {
+ /*Not implemented*/
+ }
+ else if (func == 3) /*PM*/
+ {
+ piix_pm_pci_write(addr, val, &piix);
+ }
else
{
if (addr >= 0x0f && addr < 0x4c)
@@ -119,6 +147,21 @@ void piix_write(int func, int addr, uint8_t val, void *priv)
else
pci_set_irq_routing(PCI_INTD, val & 0xf);
break;
+ case REG_SMIREQ:
+ if (piix.type <= TYPE_PIIX3)
+ {
+ card_piix[addr] &= val;
+ return;
+ }
+ break;
+ case REG_SMIREQ+1:
+ if (piix.type <= TYPE_PIIX3)
+ {
+ card_piix[addr] &= val;
+ return;
+ }
+ break;
+
}
card_piix[addr] = val;
}
@@ -127,21 +170,115 @@ void piix_write(int func, int addr, uint8_t val, void *priv)
uint8_t piix_read(int func, int addr, void *priv)
{
// pclog("piix_read: func=%d addr=%02x %04x:%08x\n", func, addr, CS, pc);
- if (func > 1)
- return 0xff;
+ if (func > ((piix.type == TYPE_PIIX4) ? 3 : 1))
+ return 0xff;
if (func == 1) /*IDE*/
{
// pclog("PIIX IDE read %02X %02X\n", addr, card_piix_ide[addr]);
return card_piix_ide[addr];
}
+ else if (func == 2) /*USB*/
+ return 0xff; /*Not implemented*/
+ else if (func == 3)
+ return piix_pm_pci_read(addr, &piix);
else
- return card_piix[addr];
+ return card_piix[addr];
}
-void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d)
+uint8_t piix_rc_read(uint16_t port, void *p)
{
+ return piix_rc;
+}
+
+void piix_rc_write(uint16_t port, uint8_t val, void *p)
+{
+ if (val & 4)
+ {
+ if (val & 2) /*Hard reset*/
+ {
+ piix_nb_reset();
+ keyboard_at_reset(); /*Reset keyboard controller to reset system flag*/
+ ide_reset_devices();
+ piix.pm.timer_offset = tsc;
+ resetx86();
+ piix.pm.apmc = piix.pm.apms = 0;
+ }
+ else
+ softresetx86();
+ }
+
+ piix_rc = val & ~4;
+}
+
+static uint8_t piix_92_read(uint16_t port, void *p)
+{
+ return piix.port_92;
+}
+static void piix_92_write(uint16_t port, uint8_t val, void *p)
+{
+ if ((mem_a20_alt ^ val) & 2)
+ {
+ mem_a20_alt = val & 2;
+ mem_a20_recalc();
+ }
+ if ((~piix.port_92 & val) & 1)
+ {
+ softresetx86();
+ cpu_set_edx();
+ }
+ piix.port_92 = val;
+}
+
+static uint8_t piix_apm_read(uint16_t port, void *p)
+{
+ piix_t *piix = (piix_t *)p;
+ uint8_t ret = 0xff;
+
+ switch (port)
+ {
+ case 0xb2:
+ ret = piix->pm.apmc;
+ break;
+
+ case 0xb3:
+ ret = piix->pm.apms;
+ break;
+ }
+// pclog("piix_apm_read: port=%04x ret=%02x\n", port, ret);
+ return ret;
+}
+
+static void piix_apm_write(uint16_t port, uint8_t val, void *p)
+{
+ piix_t *piix = (piix_t *)p;
+
+// pclog("piix_apm_write: port=%04x val=%02x\n", port, val);
+
+ switch (port)
+ {
+ case 0xb2:
+ piix->pm.apmc = val;
+ if (card_piix[REG_SMIEN] & SMIEN_APMC)
+ {
+ card_piix[REG_SMIREQ] |= SMIREQ_RAPMC;
+// pclog("APMC write causes SMI\n");
+ if (card_piix[REG_SMICNTL] & SMICNTL_CSMIGATE)
+ x86_smi_trigger();
+ }
+ break;
+
+ case 0xb3:
+ piix->pm.apms = val;
+ break;
+ }
+}
+
+static void piix_common_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_reset)())
+{
+ memset(&piix, 0, sizeof(piix_t));
+
pci_add_specific(card, piix_read, piix_write, NULL);
memset(card_piix, 0, 256);
@@ -190,4 +327,30 @@ void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d)
ide_sec_disable();
pic_init_elcrx();
+
+ io_sethandler(0x0cf9, 0x0001, piix_rc_read, NULL, NULL, piix_rc_write, NULL, NULL, NULL);
+ piix_nb_reset = nb_reset;
+
+ piix.type = TYPE_PIIX3;
+}
+
+void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_reset)())
+{
+ piix_common_init(card, pci_a, pci_b, pci_c, pci_d, nb_reset);
+
+ io_sethandler(0x00b2, 0x0002, piix_apm_read, NULL, NULL, piix_apm_write, NULL, NULL, &piix);
+}
+
+void piix4_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_reset)())
+{
+ piix_init(card, pci_a, pci_b, pci_c, pci_d, nb_reset);
+
+ piix.type = TYPE_PIIX4;
+
+ card_piix[0x02] = 0x10; card_piix[0x03] = 0x71; /*82371EB (PIIX4)*/
+
+ card_piix_ide[0x02] = 0x11; card_piix_ide[0x03] = 0x71; /*82371EB (PIIX4)*/
+
+ io_sethandler(0x0092, 0x0001, piix_92_read, NULL, NULL, piix_92_write, NULL, NULL, NULL);
+ piix_pm_init(&piix);
}
diff --git a/src/piix.h b/src/piix.h
index 88a2666..1ac8884 100644
--- a/src/piix.h
+++ b/src/piix.h
@@ -1 +1,42 @@
-void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d);
+void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_reset)());
+void piix4_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_reset)());
+
+typedef struct piix_t
+{
+ int type;
+
+ /*PIIX4*/
+ uint8_t card_pm[256];
+
+ uint16_t pmba;
+ struct
+ {
+ uint8_t apmc, apms;
+
+ uint64_t timer_offset;
+
+ uint16_t pmsts;
+ uint16_t pmen;
+ uint16_t pmcntrl;
+ uint32_t devctl;
+ uint32_t devsts;
+ uint16_t glbsts;
+ uint16_t gpen;
+ uint16_t gpsts;
+ uint32_t pcntrl;
+ uint16_t glben;
+ uint32_t glbctl;
+ uint32_t gporeg;
+
+ int dev13_enable;
+ uint16_t dev13_base, dev13_size;
+ } pm;
+
+ uint16_t smbba;
+ struct
+ {
+ uint8_t host_ctrl;
+ } smbus;
+
+ uint8_t port_92;
+} piix_t;
diff --git a/src/piix_pm.c b/src/piix_pm.c
new file mode 100644
index 0000000..e55766f
--- /dev/null
+++ b/src/piix_pm.c
@@ -0,0 +1,417 @@
+#include "ibm.h"
+#include "io.h"
+#include "piix.h"
+#include "piix_pm.h"
+#include "x86.h"
+
+#define DEVSTS_TRP_STS_DEV13 (1 << 29)
+
+#define DEVCTL_TRP_EN_DEV13 (1 << 25)
+
+#define GLBSTS_APM_STS (1 << 5)
+
+static uint8_t dev13_read(uint16_t addr, void *p)
+{
+ piix_t *piix = (piix_t *)p;
+
+// pclog("dev13_read: addr=%04x %08x\n", addr, piix.pm.devctl);
+ if (piix->pm.devctl & DEVCTL_TRP_EN_DEV13)
+ {
+ piix->pm.devsts |= DEVSTS_TRP_STS_DEV13;
+ x86_smi_trigger();
+ }
+ return 0xff;
+}
+static void dev13_write(uint16_t addr, uint8_t val, void *p)
+{
+ piix_t *piix = (piix_t *)p;
+
+// pclog("dev13_write: addr=%04x val=%02x %08x\n", addr, val, piix.pm.devctl);
+ if (piix->pm.devctl & DEVCTL_TRP_EN_DEV13)
+ {
+ piix->pm.devsts |= DEVSTS_TRP_STS_DEV13;
+ x86_smi_trigger();
+ }
+}
+
+static void dev13_recalc(piix_t *piix)
+{
+ if (piix->pm.dev13_enable)
+ io_removehandler(piix->pm.dev13_base, piix->pm.dev13_size,
+ dev13_read, NULL, NULL,
+ dev13_write, NULL, NULL, piix);
+ piix->pm.dev13_base = piix->card_pm[0x70] | (piix->card_pm[0x71] << 8);
+ piix->pm.dev13_size = (piix->card_pm[0x72] & 0xf) + 1;
+ piix->pm.dev13_enable = piix->card_pm[0x72] & 0x10;
+ if (piix->pm.dev13_enable)
+ io_sethandler(piix->pm.dev13_base, piix->pm.dev13_size,
+ dev13_read, NULL, NULL,
+ dev13_write, NULL, NULL, piix);
+}
+
+static void piix_pm_write(uint16_t port, uint8_t val, void *p)
+{
+ piix_t *piix = (piix_t *)p;
+
+// pclog("piix_pm_write: port=%04x val=%02x\n", port, val);
+ switch (port & 0x3f)
+ {
+ case 0x00:
+ piix->pm.pmsts &= ~(val & 0x31);
+ break;
+ case 0x01:
+ piix->pm.pmsts &= ~((val & 0x8d) << 8);
+ break;
+
+ case 0x02:
+ piix->pm.pmen = (piix->pm.pmen & ~0xff) | (val & 0x21);
+ break;
+ case 0x03:
+ piix->pm.pmen = (piix->pm.pmen & ~0xff00) | ((val & 0x05) << 8);
+ break;
+
+ case 0x04:
+ piix->pm.pmcntrl = (piix->pm.pmcntrl & ~0xff) | (val & 0x03);
+ break;
+ case 0x05:
+ pclog("PM reg 5 write %02x\n", val);
+ if (val & 0x20)
+ {
+ pclog("PIIX transition to power state %i\n", (val >> 2) & 7);
+ if (val == 0x20)
+ {
+ pclog("Power off\n");
+ stop_emulation_now();
+ }
+ }
+ piix->pm.pmcntrl = (piix->pm.pmcntrl & ~0xff00) | ((val & 0x1c) << 8);
+ break;
+
+ case 0x0c: case 0x0d:
+ piix->pm.gpsts &= ~(val << ((port & 1) * 8));
+ break;
+
+ case 0x0e:
+ piix->pm.pmen = (piix->pm.pmen & ~0xff) | (val & 0x01);
+ break;
+ case 0x0f:
+ piix->pm.pmen = (piix->pm.pmen & ~0xff00) | ((val & 0x0f) << 8);
+ break;
+
+ case 0x10:
+ piix->pm.pcntrl = (piix->pm.pcntrl & ~0xff) | (val & 0x1e);
+ break;
+ case 0x11:
+ piix->pm.pcntrl = (piix->pm.pcntrl & ~0xff00) | ((val & 0x3e) << 8);
+ break;
+
+ case 0x18:
+ piix->pm.glbsts &= ~(val & 0x25);
+ break;
+ case 0x19:
+ piix->pm.glbsts &= ~((val & 0x0d) << 8);
+ break;
+
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ piix->pm.devsts &= ~(val << ((port & 3) * 8));
+ break;
+
+ case 0x20:
+ piix->pm.glben = (piix->pm.glben & ~0xff) | (val & 0x01);
+ break;
+ case 0x21:
+ piix->pm.glben = (piix->pm.glben & ~0xff00) | ((val & 0x0f) << 8);
+ break;
+
+ case 0x28:
+ piix->pm.glbctl = (piix->pm.glbctl & ~0xff) | (val & 0x05);
+ break;
+ case 0x29:
+ piix->pm.glbctl = (piix->pm.glbctl & ~0xff00) | ((val & 0xff) << 8);
+ break;
+ case 0x2a:
+ piix->pm.glbctl = (piix->pm.glbctl & ~0xff0000) | ((val & 0x01) << 16);
+ break;
+ case 0x2b:
+ piix->pm.glbctl = (piix->pm.glbctl & ~0xff000000) | ((val & 0x07) << 24);
+ break;
+
+ case 0x2c:
+ piix->pm.devctl = (piix->pm.devctl & ~0xff) | val;
+ break;
+ case 0x2d:
+ piix->pm.devctl = (piix->pm.devctl & ~0xff00) | (val << 8);
+ break;
+ case 0x2e:
+ piix->pm.devctl = (piix->pm.devctl & ~0xff0000) | (val << 16);
+ break;
+ case 0x2f:
+ piix->pm.devctl = (piix->pm.devctl & ~0xff000000) | ((val & 0x0f) << 24);
+ break;
+
+ case 0x34:
+ piix->pm.gporeg = (piix->pm.gporeg & ~0xff) | val;
+ break;
+ case 0x35:
+ piix->pm.gporeg = (piix->pm.gporeg & ~0xff00) | (val << 8);
+ break;
+ case 0x36:
+ piix->pm.gporeg = (piix->pm.gporeg & ~0xff0000) | (val << 16);
+ break;
+ case 0x37:
+ piix->pm.gporeg = (piix->pm.gporeg & ~0xff000000) | (val << 24);
+ break;
+ }
+}
+static uint8_t piix_pm_read(uint16_t port, void *p)
+{
+ piix_t *piix = (piix_t *)p;
+ uint8_t ret = 0xff;
+
+ switch (port & 0x3f)
+ {
+ case 0x00: case 0x01:
+ ret = piix->pm.pmsts >> ((port & 1) * 8);
+ break;
+
+ case 0x02: case 0x03:
+ ret = piix->pm.pmen >> ((port & 1) * 8);
+ break;
+
+ case 0x04: case 0x05:
+ ret = piix->pm.pmcntrl >> ((port & 1) * 8);
+ break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ {
+ uint64_t timer = tsc - piix->pm.timer_offset;
+ uint32_t pm_timer = (timer * 3579545) / cpu_get_speed();
+
+ ret = pm_timer >> ((port & 3) * 8);
+ break;
+ }
+
+ case 0x0c: case 0x0d:
+ ret = piix->pm.gpsts >> ((port & 1) * 8);
+ break;
+
+ case 0x0e: case 0x0f:
+ ret = piix->pm.pmen >> ((port & 1) * 8);
+ break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ ret = piix->pm.pcntrl >> ((port & 3) * 8);
+ break;
+
+ case 0x14:
+ ret = 0;
+ break;
+ case 0x15:
+ ret = 0;
+ break;
+
+ case 0x18: case 0x19:
+ ret = piix->pm.glbsts >> ((port & 1) * 8);
+ break;
+
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ ret = piix->pm.devsts >> ((port & 3) * 8);
+ break;
+
+ case 0x20: case 0x21:
+ ret = piix->pm.glben >> ((port & 1) * 8);
+ break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b:
+ ret = piix->pm.glbctl >> ((port & 3) * 8);
+ break;
+
+ case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ ret = piix->pm.devctl >> ((port & 3) * 8);
+ break;
+
+ case 0x30:
+ ret = 0x00;
+ break;
+ case 0x31:
+ ret = 0x00;
+ break;
+ case 0x32:
+ /*GA686BX - bit 1 = low battery*/
+ ret = 0x00;
+ break;
+
+ case 0x34: case 0x35: case 0x36: case 0x37:
+ ret = piix->pm.gporeg >> ((port & 3) * 8);
+ break;
+
+// default:
+// fatal("piix_pm_read: unknown read %04x\n", port);
+ }
+
+// pclog("piix_pm_read: port=%04x val=%02x\n", port, ret);
+ return ret;
+}
+
+static void piix_smbus_write(uint16_t port, uint8_t val, void *p)
+{
+ piix_t *piix = (piix_t *)p;
+// pclog("piix_smbus_write: port=%04x val=%02x\n", port, val);
+
+ switch (port & 0xf)
+ {
+ case 0x2:
+ piix->smbus.host_ctrl = (val & 0x5f) | (piix->smbus.host_ctrl & 0x40);
+ break;
+ }
+}
+static uint8_t piix_smbus_read(uint16_t port, void *p)
+{
+ piix_t *piix = (piix_t *)p;
+ uint8_t ret = 0xff;
+
+ switch (port & 0x0f)
+ {
+ case 0x0:
+ ret = 0;
+ break;
+
+ case 0x2:
+ ret = piix->smbus.host_ctrl;
+ break;
+
+ case 0x5:
+ ret = 0;
+ break;
+
+// default:
+// fatal("piix_smbus_read: unknown read %04x\n", port);
+ }
+
+ return ret;
+}
+
+static uint8_t piix4_apm_read(uint16_t port, void *p)
+{
+ piix_t *piix = (piix_t *)p;
+ uint8_t ret = 0xff;
+
+ switch (port)
+ {
+ case 0xb2:
+ ret = piix->pm.apmc;
+ break;
+
+ case 0xb3:
+ ret = piix->pm.apms;
+ break;
+ }
+// pclog("piix_apm_read: port=%04x ret=%02x\n", port, ret);
+ return ret;
+}
+static void piix4_apm_write(uint16_t port, uint8_t val, void *p)
+{
+ piix_t *piix = (piix_t *)p;
+
+// pclog("piix_apm_write: port=%04x val=%02x\n", port, val);
+
+ switch (port)
+ {
+ case 0xb2:
+ piix->pm.apmc = val;
+ if (piix->card_pm[0x5b] & (1 << 1))
+ {
+ piix->pm.glbsts |= GLBSTS_APM_STS;
+// pclog("APMC write causes SMI\n");
+ x86_smi_trigger();
+ }
+ break;
+
+ case 0xb3:
+ piix->pm.apms = val;
+ break;
+ }
+}
+
+static void pm_clear_io(piix_t *piix)
+{
+ io_removehandler(piix->pmba, 0x0040, piix_pm_read, NULL, NULL, piix_pm_write, NULL, NULL, piix);
+ io_removehandler(piix->smbba, 0x0010, piix_smbus_read, NULL, NULL, piix_smbus_write, NULL, NULL, piix);
+}
+static void pm_set_io(piix_t *piix)
+{
+// pclog("pm_set_io: %02x %04x\n", piix.card_pm[0x04], piix.smbba);
+ if ((piix->card_pm[0x04] & 0x01) && piix->pmba)
+ {
+// pclog("PMBA=%04x\n", piix.pmba);
+ io_sethandler(piix->pmba, 0x0040, piix_pm_read, NULL, NULL, piix_pm_write, NULL, NULL, piix);
+ }
+ if ((piix->card_pm[0x04] & 0x01) && piix->smbba)
+ {
+// pclog("SMBBA=%04x\n", piix.smbba);
+ io_sethandler(piix->smbba, 0x0010, piix_smbus_read, NULL, NULL, piix_smbus_write, NULL, NULL, piix);
+ }
+}
+
+void piix_pm_pci_write(int addr, uint8_t val, void *p)
+{
+ piix_t *piix = (piix_t *)p;
+
+ switch (addr)
+ {
+ case 0x04:
+ pm_clear_io(piix);
+ piix->card_pm[0x04] = val & 1;
+ pm_set_io(piix);
+ break;
+ case 0x40:
+ pm_clear_io(piix);
+ piix->pmba = (piix->pmba & 0xff00) | (val & 0xc0);
+ pm_set_io(piix);
+ break;
+ case 0x41:
+ pm_clear_io(piix);
+ piix->pmba = (piix->pmba & 0xc0) | (val << 8);
+ pm_set_io(piix);
+ break;
+ case 0x58: case 0x59: case 0x5b: case 0x5c:
+ piix->card_pm[addr] = val;
+ break;
+ case 0x70: case 0x71: case 0x72:
+ piix->card_pm[addr] = val;
+ dev13_recalc(piix);
+ break;
+ case 0x90:
+ pm_clear_io(piix);
+ piix->smbba = (piix->smbba & 0xff00) | (val & 0xf0);
+ pm_set_io(piix);
+ break;
+ case 0x91:
+ pm_clear_io(piix);
+ piix->smbba = (piix->smbba & 0xf0) | (val << 8);
+ pm_set_io(piix);
+ break;
+ }
+}
+uint8_t piix_pm_pci_read(int addr, void *p)
+{
+ piix_t *piix = (piix_t *)p;
+
+ return piix->card_pm[addr];
+}
+
+void piix_pm_init(piix_t *piix)
+{
+ memset(&piix->card_pm, 0, sizeof(piix->card_pm));
+ piix->card_pm[0x00] = 0x86; piix->card_pm[0x01] = 0x80; /*Intel*/
+ piix->card_pm[0x02] = 0x13; piix->card_pm[0x03] = 0x71; /*82371EB (PIIX4)*/
+ piix->card_pm[0x06] = 0x80; piix->card_pm[0x07] = 0x02;
+ piix->card_pm[0x09] = 0x00; piix->card_pm[0x0a] = 0x80; piix->card_pm[0x0b] = 0x06; /*Bridge device*/
+ piix->card_pm[0x3d] = 0x01; /*IRQA*/
+ piix->card_pm[0x40] = 0x01;
+ piix->card_pm[0x90] = 0x01;
+ piix->pm.timer_offset = 0;
+ piix->pm.gporeg = 0x7fffbfff;
+
+ io_sethandler(0x00b2, 0x0002, piix4_apm_read, NULL, NULL, piix4_apm_write, NULL, NULL, piix);
+}
diff --git a/src/piix_pm.h b/src/piix_pm.h
new file mode 100644
index 0000000..dcc06f6
--- /dev/null
+++ b/src/piix_pm.h
@@ -0,0 +1,3 @@
+void piix_pm_init(piix_t *piix);
+void piix_pm_pci_write(int addr, uint8_t val, void *p);
+uint8_t piix_pm_pci_read(int addr, void *p);
diff --git a/src/plat-keyboard.h b/src/plat-keyboard.h
index 4b5ea03..ab8b922 100644
--- a/src/plat-keyboard.h
+++ b/src/plat-keyboard.h
@@ -1,10 +1,12 @@
#ifdef __cplusplus
extern "C" {
#endif
+ #include
+
void keyboard_init();
void keyboard_close();
void keyboard_poll_host();
- extern int pcem_key[272];
+ extern uint8_t pcem_key[272];
extern int rawinputkey[272];
#ifndef __unix
diff --git a/src/ps1.c b/src/ps1.c
index b2ea50f..e1f6fce 100644
--- a/src/ps1.c
+++ b/src/ps1.c
@@ -73,7 +73,7 @@ void ps1_write(uint16_t port, uint8_t val, void *p)
case 0x102:
lpt1_remove();
if (val & 0x04)
- serial1_init(0x3f8, 4);
+ serial1_init(0x3f8, 4, 1);
else
serial1_remove();
if (val & 0x10)
@@ -238,7 +238,7 @@ void ps1_m2121_write(uint16_t port, uint8_t val, void *p)
case 0x102:
lpt1_remove();
if (val & 0x04)
- serial1_init(0x3f8, 4);
+ serial1_init(0x3f8, 4, 1);
else
serial1_remove();
if (val & 0x10)
@@ -301,3 +301,65 @@ void ps1mb_m2121_init()
mem_remap_top_384k();
}
+
+
+/*Not sure what this SuperIO chip is, so define it here for now*/
+static struct
+{
+ int idx;
+ uint8_t regs[3];
+} ps1_m2133_superio;
+
+static uint16_t ps1_lpt_io[4] = {0x378, 0x3bc, 0x278, 0x378};
+static uint16_t ps1_com_io[4] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
+
+static uint8_t ps1_m2133_read(uint16_t port, void *p)
+{
+ uint8_t ret = 0xff;
+ switch (port)
+ {
+ case 0x398:
+ ret = ps1_m2133_superio.idx;
+ break;
+
+ case 0x399:
+ if (ps1_m2133_superio.idx < 3)
+ ret = ps1_m2133_superio.regs[ps1_m2133_superio.idx];
+ break;
+ }
+ return ret;
+}
+
+static void ps1_m2133_write(uint16_t port, uint8_t val, void *p)
+{
+// pclog("ps1_m2133_write: port=%04x val=%02x\n", port, val);
+ switch (port)
+ {
+ case 0x398:
+ ps1_m2133_superio.idx = val;
+ break;
+
+ case 0x399:
+ if (ps1_m2133_superio.idx < 3)
+ {
+ ps1_m2133_superio.regs[ps1_m2133_superio.idx] = val;
+
+ lpt1_remove();
+ serial1_remove();
+ serial2_remove();
+
+ if (ps1_m2133_superio.regs[0] & 1)
+ lpt1_init(ps1_lpt_io[ps1_m2133_superio.regs[1] & 3]);
+ if (ps1_m2133_superio.regs[0] & 2)
+ serial1_set(ps1_com_io[(ps1_m2133_superio.regs[1] >> 2) & 3], 4);
+ if (ps1_m2133_superio.regs[0] & 4)
+ serial2_set(ps1_com_io[(ps1_m2133_superio.regs[1] >> 4) & 3], 3);
+ }
+ break;
+ }
+}
+
+void ps1mb_m2133_init(void)
+{
+ io_sethandler(0x0398, 0x0002, ps1_m2133_read, NULL, NULL, ps1_m2133_write, NULL, NULL, NULL);
+}
diff --git a/src/ps1.h b/src/ps1.h
index c054bcb..7253c8b 100644
--- a/src/ps1.h
+++ b/src/ps1.h
@@ -1,2 +1,3 @@
void ps1mb_init();
void ps1mb_m2121_init();
+void ps1mb_m2133_init(void);
diff --git a/src/ps2.c b/src/ps2.c
index 6334666..fe0d6a9 100644
--- a/src/ps2.c
+++ b/src/ps2.c
@@ -68,7 +68,7 @@ void ps2_write(uint16_t port, uint8_t val, void *p)
case 0x102:
lpt1_remove();
if (val & 0x04)
- serial1_init(0x3f8, 4);
+ serial1_init(0x3f8, 4, 1);
else
serial1_remove();
if (val & 0x10)
diff --git a/src/ps2_mca.c b/src/ps2_mca.c
index 1e8b77f..dd4e024 100644
--- a/src/ps2_mca.c
+++ b/src/ps2_mca.c
@@ -9,6 +9,7 @@
#include "ps2_nvr.h"
#include "rom.h"
#include "serial.h"
+#include "vid_vga.h"
#include "x86.h"
//static uint8_t ps2_92, ps2_94, ps2_102, ps2_103, ps2_104, ps2_105, ps2_190;
@@ -314,9 +315,9 @@ static void model_50_write(uint16_t port, uint8_t val)
if (val & 0x04)
{
if (val & 0x08)
- serial1_init(0x3f8, 4);
+ serial1_init(0x3f8, 4, 1);
else
- serial1_init(0x2f8, 3);
+ serial1_init(0x2f8, 3, 1);
}
else
serial1_remove();
@@ -370,9 +371,9 @@ static void model_55sx_write(uint16_t port, uint8_t val)
if (val & 0x04)
{
if (val & 0x08)
- serial1_init(0x3f8, 4);
+ serial1_init(0x3f8, 4, 1);
else
- serial1_init(0x2f8, 3);
+ serial1_init(0x2f8, 3, 1);
}
else
serial1_remove();
@@ -444,9 +445,9 @@ static void model_70_type3_write(uint16_t port, uint8_t val)
if (val & 0x04)
{
if (val & 0x08)
- serial1_init(0x3f8, 4);
+ serial1_init(0x3f8, 4, 1);
else
- serial1_init(0x2f8, 3);
+ serial1_init(0x2f8, 3, 1);
}
else
serial1_remove();
@@ -493,9 +494,9 @@ static void model_80_write(uint16_t port, uint8_t val)
if (val & 0x04)
{
if (val & 0x08)
- serial1_init(0x3f8, 4);
+ serial1_init(0x3f8, 4, 1);
else
- serial1_init(0x2f8, 3);
+ serial1_init(0x2f8, 3, 1);
}
else
serial1_remove();
@@ -652,6 +653,8 @@ static void ps2_mca_write(uint16_t port, uint8_t val, void *p)
ps2.setup = val;
break;
case 0x96:
+ if ((val & 0x80) && !(ps2.adapter_setup & 0x80))
+ mca_reset();
ps2.adapter_setup = val;
mca_set_index(val & 7);
break;
@@ -671,7 +674,15 @@ static void ps2_mca_write(uint16_t port, uint8_t val, void *p)
if (!(ps2.setup & PS2_SETUP_IO))
ps2.planar_write(port, val);
else if (!(ps2.setup & PS2_SETUP_VGA))
+ {
+ if (mb_vga)
+ {
+ vga_disable(mb_vga);
+ if (val & 1)
+ vga_enable(mb_vga);
+ }
ps2.pos_vga = val;
+ }
else if (ps2.adapter_setup & PS2_ADAPTER_SETUP)
mca_write(port, val);
break;
@@ -1018,7 +1029,7 @@ void ps2_mca_board_model_70_type34_init(int is_type4)
break;
}
- mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, NULL);
+ mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, NULL, NULL);
mem_mapping_add(&ps2.expansion_mapping,
0x800000,
(mem_size - 8192)*1024,
@@ -1119,7 +1130,7 @@ void ps2_mca_board_model_80_type2_init()
break;
}
- mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, NULL);
+ mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, NULL, NULL);
mem_mapping_add(&ps2.expansion_mapping,
0x400000,
(mem_size - 4096)*1024,
diff --git a/src/pzx.c b/src/pzx.c
new file mode 100644
index 0000000..801ce72
--- /dev/null
+++ b/src/pzx.c
@@ -0,0 +1,419 @@
+/************************************************************************
+
+ PCem: IBM 5150 Cassette support
+
+ Copyright (C) 2019 John Elliott
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*************************************************************************/
+
+#include
+#include "ibm.h"
+#include "pzx.h"
+
+/* This module is intended to abstract all the details of a PZX file and
+ * emit its contents as a bitstream in a form suitable for PCem. Similar
+ * modules could be written to add support for other tape formats such as TZX,
+ * TAP or CSW. */
+
+#define CAS_LOG(x) pclog x
+/* #define CAS_LOG(x) */
+
+static uint32_t peek2(uint8_t *data)
+{
+ return (((uint32_t)data[1]) << 8) | data[0];
+}
+
+static uint32_t peek4(uint8_t *data)
+{
+ return (((uint32_t)data[3]) << 24) |
+ (((uint32_t)data[2]) << 16) |
+ (((uint32_t)data[1]) << 8) | data[0];
+}
+
+/* Cue up the next pulse definition from the current PULS block. */
+static void pzx_parse_pulse(pzxfile_t *pzx)
+{
+ pzx->puls_duration = peek2(pzx->curblock + pzx->puls_ptr);
+ pzx->puls_ptr += 2;
+ if (pzx->puls_duration > 0x8000)
+ {
+ pzx->puls_count = pzx->puls_duration & 0x7FFF;
+ pzx->puls_duration = peek2(pzx->curblock + pzx->puls_ptr);
+ pzx->puls_ptr += 2;
+ }
+ if (pzx->puls_duration >= 0x8000)
+ {
+ pzx->puls_duration &= 0x7FFF;
+ pzx->puls_duration <<= 16;
+ pzx->puls_duration |= peek2(pzx->curblock + pzx->puls_ptr);
+ pzx->puls_ptr += 2;
+ }
+ if (!pzx->puls_count) pzx->puls_count = 1;
+}
+
+
+
+void pzx_init(pzxfile_t *pzx)
+{
+ memset(pzx, 0, sizeof(pzxfile_t));
+ pzx->state = PZX_CLOSED;
+}
+
+/* Load the next block from a PZX-format file.
+ *
+ * Returns block if successful, NULL if end of file or error
+ * Caller must free the block with free(). */
+uint8_t *pzx_load_block(FILE *fp)
+{
+ uint8_t block_header[8];
+ uint8_t *block_data;
+ uint32_t block_len;
+
+ /* The first 8 bytes of a PZX block are fixed: the first 4 give
+ * the ID, the second 4 the length (excluding the header itself) */
+ if (fread(block_header, 1, 8, fp) < 8) return NULL; /* EoF */
+
+ block_len = peek4(block_header + 4);
+ block_data = malloc(8 + block_len);
+ if (!block_data) return NULL;
+ memcpy(block_data, block_header, 8);
+ if (!block_len) /* Block is only the header */
+ {
+/* CAS_LOG(("Loaded PZX block: %-4.4s\n", block_data)); */
+ return block_data;
+ }
+ if (fread(block_data + 8, 1, block_len, fp) < block_len)
+ {
+ free(block_data); /* Unexpected EoF */
+ return NULL;
+ }
+/* CAS_LOG(("Loaded PZX block: %-4.4s\n", block_data)); */
+ return block_data;
+}
+
+
+/* Search the current file for PZX version headers and check they're all 1.x */
+static const char * pzx_check_version(FILE *fp)
+{
+ uint8_t *block;
+ static char message[80];
+
+ rewind(fp);
+ while ( (block = pzx_load_block(fp)) )
+ {
+ if (!memcmp(block, "PZXT", 4))
+ {
+ CAS_LOG(("PZX version %d.%d\n", block[8], block[9]));
+ if (block[8] != 1)
+ {
+ sprintf(message, "Unsupported PZX version %d.%d\n", block[8], block[9]);
+ free(block);
+ return message;
+ }
+ }
+ free(block);
+ }
+ rewind(fp);
+ return NULL;
+}
+
+
+const char *pzx_open(pzxfile_t *pzx, FILE *fp)
+{
+ const char *result;
+
+ rewind(fp);
+ /* Check that this file is compatible */
+ result = pzx_check_version(fp);
+ if (result) return result;
+
+ pzx->level = 0;
+ pzx->state = PZX_IDLE;
+ pzx->input = fp;
+ return NULL;
+}
+
+void pzx_close(pzxfile_t *pzx)
+{
+ if (pzx->input)
+ {
+ fclose(pzx->input);
+ pzx->input = NULL;
+ }
+ if (pzx->curblock)
+ {
+ free(pzx->curblock);
+ pzx->curblock = NULL;
+ }
+ pzx->state = PZX_CLOSED;
+}
+
+/* Read the next block of type DATA, PAUS or PULS */
+int pzx_next_block(pzxfile_t *pzx)
+{
+ long pos;
+
+ pos = ftell(pzx->input);
+ while (pzx->state == PZX_IDLE)
+ {
+ uint8_t *blk;
+
+ /* In idle state there should be no current block. But
+ * make sure of that */
+ if (pzx->curblock)
+ {
+ free(pzx->curblock);
+ pzx->curblock = NULL;
+ }
+
+ /* Load the next block */
+ blk = pzx_load_block(pzx->input);
+
+ /* If that didn't load we've reached the end of file; wrap to
+ * beginning. */
+ if (!blk)
+ {
+ rewind(pzx->input);
+ blk = pzx_load_block(pzx->input);
+ if (!blk) /* Couldn't even load first block */
+ {
+ pzx_close(pzx);
+ return 0;
+ }
+ /* Have we read the whole file and come back to where
+ * we were? */
+ if (ftell(pzx->input) == pos)
+ {
+ free(blk);
+ pzx_close(pzx);
+ return 0;
+ }
+ }
+ /* We have loaded the next block. What is it? */
+ if (!memcmp(blk, "PULS", 4))
+ {
+ pzx->state = PZX_IN_PULS;
+ pzx->curblock = blk;
+ pzx->puls_len = 8 + peek4(blk + 4);
+ pzx->puls_ptr = 8;
+ pzx->puls_count = 0;
+ pzx->puls_remain = 0;
+ pzx->puls_duration = 0;
+ pzx->level = 0;
+ CAS_LOG(("Beginning PULS block\n"));
+ }
+ else if (!memcmp(blk, "PAUS", 4))
+ {
+ pzx->state = PZX_IN_PAUS;
+ pzx->curblock = blk;
+ pzx->paus_remain = peek4(blk + 8);
+ pzx->level = (pzx->paus_remain >> 31);
+ pzx->paus_remain &= 0x7FFFFFFF;
+ CAS_LOG(("Beginning PAUS block, duration=%d\n",
+ pzx->paus_remain));
+ }
+ else if (!memcmp(blk, "DATA", 4))
+ {
+ pzx->state = PZX_IN_DATA;
+ pzx->curblock = blk;
+ pzx->data_bits = peek4(blk + 8);
+ pzx->level = (pzx->data_bits >> 31);
+ pzx->data_bits &= 0x7FFFFFFF;
+ pzx->data_tail = peek2(blk + 12);
+ pzx->data_p0 = blk[14];
+ pzx->data_p1 = blk[15];
+ pzx->data_p = 0;
+ pzx->data_w = 16;
+ pzx->data_remain = 0;
+ pzx->data_ptr = 16 + 2 * (pzx->data_p0 + pzx->data_p1);
+ pzx->data_mask = 0x80;
+ CAS_LOG(("Beginning DATA block, length=%d p0=%d p1=%d"
+ " data_ptr=%d\n",
+ pzx->data_bits,
+ pzx->data_p0, pzx->data_p1,
+ pzx->data_ptr));
+ }
+ }
+ return 1;
+}
+
+static void pzx_endblock(pzxfile_t *pzx)
+{
+ if (pzx->curblock) free(pzx->curblock);
+ pzx->curblock = NULL;
+ pzx->state = PZX_IDLE;
+}
+
+/* PAUS is easy - just run the timer down */
+static int pzx_advance_paus(pzxfile_t *pzx, int time)
+{
+ if (pzx->paus_remain > time)
+ {
+ pzx->paus_remain -= time;
+ return 0;
+ }
+ time -= pzx->paus_remain;
+ pzx_endblock(pzx);
+ return time;
+}
+
+
+
+
+
+
+static int pzx_advance_puls(pzxfile_t *pzx, int time)
+{
+ /* At the start of a pulse sequence? */
+ if (pzx->puls_count == 0)
+ {
+ pzx_parse_pulse(pzx);
+ pzx->puls_remain = pzx->puls_duration;
+ }
+ /* Does sample trigger a pulse change? If not, that's easy. */
+ if (time < pzx->puls_remain)
+ {
+ pzx->puls_remain -= time;
+ return 0;
+ }
+ /* Sample does trigger a pulse change */
+ time -= pzx->puls_remain;
+ /* If there's another pulse in the current sequence, that's
+ * straightforward; just flip the level and continue */
+ --pzx->puls_count;
+ pzx->level = !pzx->level;
+ if (pzx->puls_count)
+ {
+ pzx->puls_remain = pzx->puls_duration;
+ return time;
+ }
+ /* If we've reached the end of the pulse sequence, there may be
+ * another one */
+ if (pzx->puls_ptr < pzx->puls_len)
+ {
+ return time;
+ }
+ /* If there isn't another one, it's the end of the block */
+ pzx_endblock(pzx);
+ return time;
+}
+
+
+/* Decode a DATA block */
+static int pzx_advance_data(pzxfile_t *pzx, int time)
+{
+ uint8_t bit;
+
+ /* Reached end of data? */
+ if (pzx->data_bits == 0)
+ {
+ /* Time interval is covered by the tail bit */
+ if (pzx->data_tail > time)
+ {
+ pzx->data_tail -= time;
+ return 0;
+ }
+ /* Have run out of block */
+ time -= pzx->data_tail;
+ pzx_endblock(pzx);
+ return time;
+ }
+ /* No more time remaining on the current bit? */
+ if (pzx->data_p < 1 && !pzx->data_remain)
+ {
+ bit = pzx->curblock[pzx->data_ptr] & pzx->data_mask;
+ pzx->data_mask >>= 1;
+ if (!pzx->data_mask)
+ {
+ pzx->data_mask = 0x80;
+ ++pzx->data_ptr;
+ }
+ --pzx->data_bits;
+
+ if (bit)
+ {
+ pzx->data_p = pzx->data_p1;
+ pzx->data_w = 16 + 2 * pzx->data_p0;
+ pzx->data_remain = 0;
+ }
+ else
+ {
+ pzx->data_p = pzx->data_p0;
+ pzx->data_w = 16;
+ pzx->data_remain = 0;
+ }
+ }
+ /* See if we've started processing the current waveform. If not,
+ * load its first element (assuming that there is one) */
+ if (!pzx->data_remain)
+ {
+ if (pzx->data_p)
+ {
+ pzx->data_remain = peek2(pzx->curblock + pzx->data_w);
+ pzx->data_w += 2;
+ pzx->data_p--;
+ }
+ }
+ if (pzx->data_remain > time)
+ {
+ /* Time advance is contained within current wave */
+ pzx->data_remain -= time;
+ return 0;
+ }
+ else /* Move on to next element of wave / next bit / next block */
+ {
+ time -= pzx->data_remain;
+ pzx->data_remain = 0;
+ pzx->level = !pzx->level;
+ }
+
+ return time;
+}
+
+
+
+
+int pzx_advance(pzxfile_t *pzx, int time)
+{
+ if (pzx->state == PZX_CLOSED) return 0; /* No tape loaded */
+
+ while (time)
+ {
+ switch (pzx->state)
+ {
+ case PZX_IDLE:
+ if (!pzx_next_block(pzx)) return 0;
+ break;
+ case PZX_IN_PULS:
+ time = pzx_advance_puls(pzx, time);
+ break;
+ case PZX_IN_PAUS:
+ time = pzx_advance_paus(pzx, time);
+ break;
+ case PZX_IN_DATA:
+ time = pzx_advance_data(pzx, time);
+ break;
+ case PZX_CLOSED: /*Should never get here*/
+ return 0;
+
+ }
+ }
+ return pzx->level;
+}
+
+
+
diff --git a/src/pzx.h b/src/pzx.h
new file mode 100644
index 0000000..94d5ca1
--- /dev/null
+++ b/src/pzx.h
@@ -0,0 +1,71 @@
+/************************************************************************
+
+ PCem: IBM 5150 cassette support
+
+ Copyright (C) 2019 John Elliott
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*************************************************************************/
+
+typedef enum
+{
+ PZX_CLOSED, /* File is not open */
+ PZX_IDLE, /* File is open, no block loaded */
+ PZX_IN_PULS, /* File is open, current block is a PULS block */
+ PZX_IN_DATA, /* File is open, current block is a DATA block */
+ PZX_IN_PAUS, /* File is open, current block is a PAUS block */
+} PZX_STATE;
+
+
+typedef struct pzxfile_t
+{
+ FILE *input; /* Input PZX file */
+ uint8_t *curblock; /* Currently-loaded block, if any */
+ int level; /* Current signal level */
+ PZX_STATE state; /* State machine current status */
+/* State variables for PULS */
+ uint32_t puls_ptr; /* Pointer within PULS block */
+ uint32_t puls_len; /* Length of PULS block */
+ uint32_t puls_count; /* Count of pulses */
+ uint32_t puls_duration; /* Duration of each pulse */
+ uint32_t puls_remain; /* Time remaining in this pulse */
+/* State variables for PAUS */
+ uint32_t paus_remain; /* Time remaining in this pause */
+/* State variables for DATA */
+ uint32_t data_ptr; /* Pointer within DATA block */
+ uint32_t data_bits; /* Count of bits */
+ uint16_t data_tail; /* Length of pulse after last bit */
+ uint8_t data_mask; /* Mask for current bit */
+ uint8_t data_p0; /* Length of 0 encoding */
+ uint8_t data_p1; /* Length of 1 encoding */
+ int data_p; /* Current sequence being emitted */
+ uint32_t data_w; /* Current waveform */
+ uint32_t data_remain; /* Current data pulse time remaining */
+} pzxfile_t;
+
+uint8_t *pzx_load_block(FILE *fp);
+
+/* Initialise structure */
+void pzx_init(pzxfile_t *pzx);
+
+/* Open file for input */
+const char *pzx_open(pzxfile_t *pzx, FILE *fp);
+
+/* Close file */
+void pzx_close(pzxfile_t *pzx);
+
+/* Advance by 'time' samples (3.5MHz sample rate) and return current state */
+int pzx_advance(pzxfile_t *pzx, int time);
diff --git a/src/resources.h b/src/resources.h
index 69d9306..02b4772 100644
--- a/src/resources.h
+++ b/src/resources.h
@@ -10,6 +10,8 @@
#define IDM_BPB_DISABLE 40015
#define IDM_CONFIG 40020
#define IDM_STATUS 40030
+#define IDM_CASSETTE_LOAD 40040
+#define IDM_CASSETTE_EJECT 40041
#define IDM_VID_RESIZE 40050
#define IDM_VID_REMEMBER 40051
#define IDM_VID_ASPECT 40052
@@ -122,6 +124,7 @@
#define IDC_EDIT_F_FN 1233
#define IDC_HDTYPE 1280
+#define IDC_HDFORMAT 1281
#define IDC_CONFIGUREVID 1200
#define IDC_CONFIGURESND 1201
diff --git a/src/rtc.c b/src/rtc.c
index d1a0515..323e5a6 100644
--- a/src/rtc.c
+++ b/src/rtc.c
@@ -42,7 +42,7 @@ static int rtc_is_leap(int org_year)
static int rtc_get_days(int org_month, int org_year)
{
if (org_month != 2)
- return rtc_days_in_month[org_month];
+ return rtc_days_in_month[org_month-1];
else
return rtc_is_leap(org_year) ? 29 : 28;
}
diff --git a/src/rtc_tc8521.c b/src/rtc_tc8521.c
index e5b8649..cfc1a36 100644
--- a/src/rtc_tc8521.c
+++ b/src/rtc_tc8521.c
@@ -37,7 +37,7 @@ static int rtc_is_leap(int org_year)
static int rtc_get_days(int org_month, int org_year)
{
if (org_month != 2)
- return rtc_days_in_month[org_month];
+ return rtc_days_in_month[org_month-1];
else
return rtc_is_leap(org_year) ? 29 : 28;
}
diff --git a/src/scamp.c b/src/scamp.c
new file mode 100644
index 0000000..93c716f
--- /dev/null
+++ b/src/scamp.c
@@ -0,0 +1,766 @@
+#include "ibm.h"
+#include "io.h"
+#include "mem.h"
+#include "scamp.h"
+
+static struct
+{
+ int cfg_index;
+ uint8_t cfg_regs[256];
+ int cfg_enable;
+
+ int ram_config;
+
+ mem_mapping_t ram_mapping[2];
+ uint32_t ram_virt_base[2], ram_phys_base[2];
+ uint32_t ram_mask[2];
+ int row_virt_shift[2], row_phys_shift[2];
+ int ram_interleaved[2];
+ int ibank_shift[2];
+
+ uint8_t port_92;
+} scamp;
+
+#define CFG_ID 0x00
+#define CFG_SLTPTR 0x02
+#define CFG_RAMMAP 0x03
+#define CFG_EMSEN1 0x0b
+#define CFG_EMSEN2 0x0c
+#define CFG_ABAXS 0x0e
+#define CFG_CAXS 0x0f
+#define CFG_DAXS 0x10
+#define CFG_FEAXS 0x11
+
+#define ID_VL82C311 0xd6
+
+#define RAMMAP_REMP386 (1 << 4)
+
+/*Commodore SL386SX requires proper memory slot decoding to detect memory size.
+ Therefore we emulate the SCAMP memory address decoding, and therefore are
+ limited to the DRAM combinations supported by the actual chip*/
+enum
+{
+ BANK_NONE,
+ BANK_256K,
+ BANK_256K_INTERLEAVED,
+ BANK_1M,
+ BANK_1M_INTERLEAVED,
+ BANK_4M,
+ BANK_4M_INTERLEAVED
+};
+
+static const struct
+{
+ int size_kb;
+ int rammap;
+ int bank[2];
+} ram_configs[] =
+{
+ {512, 0x0, {BANK_256K, BANK_NONE}},
+ {1024, 0x1, {BANK_256K_INTERLEAVED, BANK_NONE}},
+ {1536, 0x2, {BANK_256K_INTERLEAVED, BANK_256K}},
+ {2048, 0x3, {BANK_256K_INTERLEAVED, BANK_256K_INTERLEAVED}},
+ {3072, 0xc, {BANK_256K_INTERLEAVED, BANK_1M}},
+ {4096, 0x5, {BANK_1M_INTERLEAVED, BANK_NONE}},
+ {5120, 0xd, {BANK_256K_INTERLEAVED, BANK_1M_INTERLEAVED}},
+ {6144, 0x6, {BANK_1M_INTERLEAVED, BANK_1M}},
+ {8192, 0x7, {BANK_1M_INTERLEAVED, BANK_1M_INTERLEAVED}},
+ {12288, 0xe, {BANK_1M_INTERLEAVED, BANK_4M}},
+ {16384, 0x9, {BANK_4M_INTERLEAVED, BANK_NONE}},
+};
+
+static const struct
+{
+ int bank[2];
+ int remapped;
+} rammap[16] =
+{
+ {{BANK_256K, BANK_NONE}, 0},
+ {{BANK_256K_INTERLEAVED, BANK_NONE}, 0},
+ {{BANK_256K_INTERLEAVED, BANK_256K}, 0},
+ {{BANK_256K_INTERLEAVED, BANK_256K_INTERLEAVED}, 0},
+
+ {{BANK_1M, BANK_NONE}, 0},
+ {{BANK_1M_INTERLEAVED, BANK_NONE}, 0},
+ {{BANK_1M_INTERLEAVED, BANK_1M}, 0},
+ {{BANK_1M_INTERLEAVED, BANK_1M_INTERLEAVED}, 0},
+
+ {{BANK_4M, BANK_NONE}, 0},
+ {{BANK_4M_INTERLEAVED, BANK_NONE}, 0},
+ {{BANK_NONE, BANK_4M}, 1}, /*Bank 2 remapped to 0*/
+ {{BANK_NONE, BANK_4M_INTERLEAVED}, 1}, /*Banks 2/3 remapped to 0/1*/
+
+ {{BANK_256K_INTERLEAVED, BANK_1M}, 0},
+ {{BANK_256K_INTERLEAVED, BANK_1M_INTERLEAVED}, 0},
+ {{BANK_1M_INTERLEAVED, BANK_4M}, 0},
+ {{BANK_1M_INTERLEAVED, BANK_4M_INTERLEAVED}, 0}, /*Undocumented - probably wrong!*/
+};
+
+/*The column bits masked when using 256kbit DRAMs in 4Mbit mode aren't contiguous,
+ so we use separate routines for that special case*/
+static uint8_t ram_mirrored_256k_in_4mi_read(uint32_t addr, void *p)
+{
+ int bank = (intptr_t)p;
+ int row, column, byte;
+
+ addr -= scamp.ram_virt_base[bank];
+ byte = addr & 1;
+ if (!scamp.ram_interleaved[bank])
+ {
+ if (addr & 0x400)
+ return 0xff;
+
+ addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1);
+ column = (addr >> 1) & scamp.ram_mask[bank];
+ row = ((addr & 0xff000) >> 13) | (((addr & 0x200000) >> 22) << 9);
+
+ addr = byte | (column << 1) | (row << scamp.row_phys_shift[bank]);
+ }
+ else
+ {
+ column = (addr >> 1) & ((scamp.ram_mask[bank] << 1) | 1);
+ row = ((addr & 0x1fe000) >> 13) | (((addr & 0x400000) >> 22) << 9);
+
+ addr = byte | (column << 1) | (row << (scamp.row_phys_shift[bank]+1));
+ }
+
+ return ram[addr + scamp.ram_phys_base[bank]];
+}
+static void ram_mirrored_256k_in_4mi_write(uint32_t addr, uint8_t val, void *p)
+{
+ int bank = (intptr_t)p;
+ int row, column, byte;
+
+ addr -= scamp.ram_virt_base[bank];
+ byte = addr & 1;
+ if (!scamp.ram_interleaved[bank])
+ {
+ if (addr & 0x400)
+ return;
+
+ addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1);
+ column = (addr >> 1) & scamp.ram_mask[bank];
+ row = ((addr & 0xff000) >> 13) | (((addr & 0x200000) >> 22) << 9);
+
+ addr = byte | (column << 1) | (row << scamp.row_phys_shift[bank]);
+ }
+ else
+ {
+ column = (addr >> 1) & ((scamp.ram_mask[bank] << 1) | 1);
+ row = ((addr & 0x1fe000) >> 13) | (((addr & 0x400000) >> 22) << 9);
+
+ addr = byte | (column << 1) | (row << (scamp.row_phys_shift[bank]+1));
+ }
+
+ ram[addr + scamp.ram_phys_base[bank]] = val;
+}
+
+/*Read/write handlers for interleaved memory banks. We must keep CPU and ram array
+ mapping linear, otherwise we won't be able to execute code from interleaved banks*/
+static uint8_t ram_mirrored_interleaved_read(uint32_t addr, void *p)
+{
+ int bank = (intptr_t)p;
+ int row, column, byte;
+
+ addr -= scamp.ram_virt_base[bank];
+ byte = addr & 1;
+ if (!scamp.ram_interleaved[bank])
+ {
+ if (addr & 0x400)
+ return 0xff;
+
+ addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1);
+ column = (addr >> 1) & scamp.ram_mask[bank];
+ row = (addr >> scamp.row_virt_shift[bank]) & scamp.ram_mask[bank];
+
+ addr = byte | (column << 1) | (row << scamp.row_phys_shift[bank]);
+ }
+ else
+ {
+ column = (addr >> 1) & ((scamp.ram_mask[bank] << 1) | 1);
+ row = (addr >> (scamp.row_virt_shift[bank]+1)) & scamp.ram_mask[bank];
+
+ addr = byte | (column << 1) | (row << (scamp.row_phys_shift[bank]+1));
+ }
+
+ return ram[addr + scamp.ram_phys_base[bank]];
+}
+static void ram_mirrored_interleaved_write(uint32_t addr, uint8_t val, void *p)
+{
+ int bank = (intptr_t)p;
+ int row, column, byte;
+
+ addr -= scamp.ram_virt_base[bank];
+ byte = addr & 1;
+ if (!scamp.ram_interleaved[bank])
+ {
+ if (addr & 0x400)
+ return;
+
+ addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1);
+ column = (addr >> 1) & scamp.ram_mask[bank];
+ row = (addr >> scamp.row_virt_shift[bank]) & scamp.ram_mask[bank];
+
+ addr = byte | (column << 1) | (row << scamp.row_phys_shift[bank]);
+ }
+ else
+ {
+ column = (addr >> 1) & ((scamp.ram_mask[bank] << 1) | 1);
+ row = (addr >> (scamp.row_virt_shift[bank]+1)) & scamp.ram_mask[bank];
+
+ addr = byte | (column << 1) | (row << (scamp.row_phys_shift[bank]+1));
+ }
+
+ ram[addr + scamp.ram_phys_base[bank]] = val;
+}
+
+static uint8_t ram_mirrored_read(uint32_t addr, void *p)
+{
+ int bank = (intptr_t)p;
+ int row, column, byte;
+
+ addr -= scamp.ram_virt_base[bank];
+ byte = addr & 1;
+ column = (addr >> 1) & scamp.ram_mask[bank];
+ row = (addr >> scamp.row_virt_shift[bank]) & scamp.ram_mask[bank];
+ addr = byte | (column << 1) | (row << scamp.row_phys_shift[bank]);
+
+ return ram[addr + scamp.ram_phys_base[bank]];
+}
+static void ram_mirrored_write(uint32_t addr, uint8_t val, void *p)
+{
+ int bank = (intptr_t)p;
+ int row, column, byte;
+
+ addr -= scamp.ram_virt_base[bank];
+ byte = addr & 1;
+ column = (addr >> 1) & scamp.ram_mask[bank];
+ row = (addr >> scamp.row_virt_shift[bank]) & scamp.ram_mask[bank];
+ addr = byte | (column << 1) | (row << scamp.row_phys_shift[bank]);
+
+ ram[addr + scamp.ram_phys_base[bank]] = val;
+}
+
+static void recalc_mappings(void)
+{
+ int c;
+ uint32_t virt_base = 0;
+ uint8_t cur_rammap = scamp.cfg_regs[CFG_RAMMAP] & 0xf;
+ intptr_t bank_nr = 0;
+
+ for (c = 0; c < 2; c++)
+ mem_mapping_disable(&scamp.ram_mapping[c]);
+
+ /*Once the BIOS programs the correct DRAM configuration, switch to regular
+ linear memory mapping*/
+ if (cur_rammap == ram_configs[scamp.ram_config].rammap)
+ {
+ mem_mapping_set_handler(&ram_low_mapping,
+ mem_read_ram, mem_read_ramw, mem_read_raml,
+ mem_write_ram, mem_write_ramw, mem_write_raml);
+ mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
+ mem_mapping_enable(&ram_high_mapping);
+ return;
+ }
+ else
+ {
+ mem_mapping_set_handler(&ram_low_mapping,
+ ram_mirrored_read, NULL, NULL,
+ ram_mirrored_write, NULL, NULL);
+ mem_mapping_disable(&ram_low_mapping);
+ }
+
+ if (rammap[cur_rammap].bank[0] == BANK_NONE)
+ bank_nr = 1;
+
+ pclog("Bank remap, cur_rammap=%x\n", cur_rammap);
+
+ for (; bank_nr < 2; bank_nr++)
+ {
+ uint32_t old_virt_base = virt_base;
+ int phys_bank = ram_configs[scamp.ram_config].bank[bank_nr];
+
+ pclog(" Bank %i: phys_bank=%i rammap_bank=%i virt_base=%08x phys_base=%08x\n", bank_nr, phys_bank, rammap[cur_rammap].bank[bank_nr], virt_base, scamp.ram_phys_base[bank_nr]);
+ scamp.ram_virt_base[bank_nr] = virt_base;
+
+ if (virt_base == 0)
+ {
+ switch (rammap[cur_rammap].bank[bank_nr])
+ {
+ case BANK_NONE:
+ fatal("Bank 0 is empty!\n");
+ break;
+
+ case BANK_256K:
+ if (phys_bank != BANK_NONE)
+ {
+ mem_mapping_set_addr(&ram_low_mapping, 0, 0x80000);
+ mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
+ }
+ virt_base += 512*1024;
+ scamp.row_virt_shift[bank_nr] = 10;
+ break;
+
+ case BANK_256K_INTERLEAVED:
+ if (phys_bank != BANK_NONE)
+ {
+ mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
+ mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
+ }
+ virt_base += 512*1024*2;
+ scamp.row_virt_shift[bank_nr] = 10;
+ break;
+
+ case BANK_1M:
+ if (phys_bank != BANK_NONE)
+ {
+ mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
+ mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
+ mem_mapping_set_addr(&scamp.ram_mapping[bank_nr], 0x100000, 0x100000);
+ mem_mapping_set_exec(&scamp.ram_mapping[bank_nr], &ram[scamp.ram_phys_base[bank_nr] + 0x100000]);
+ }
+ virt_base += 2048*1024;
+ scamp.row_virt_shift[bank_nr] = 11;
+ break;
+
+ case BANK_1M_INTERLEAVED:
+ if (phys_bank != BANK_NONE)
+ {
+ mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
+ mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
+ mem_mapping_set_addr(&scamp.ram_mapping[bank_nr], 0x100000, 0x300000);
+ mem_mapping_set_exec(&scamp.ram_mapping[bank_nr], &ram[scamp.ram_phys_base[bank_nr] + 0x100000]);
+ }
+ virt_base += 2048*1024*2;
+ scamp.row_virt_shift[bank_nr] = 11;
+ break;
+
+ case BANK_4M:
+ if (phys_bank != BANK_NONE)
+ {
+ mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
+ mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
+ mem_mapping_set_addr(&scamp.ram_mapping[bank_nr], 0x100000, 0x700000);
+ mem_mapping_set_exec(&scamp.ram_mapping[bank_nr], &ram[scamp.ram_phys_base[bank_nr] + 0x100000]);
+ }
+ virt_base += 8192*1024;
+ scamp.row_virt_shift[bank_nr] = 12;
+ break;
+
+ case BANK_4M_INTERLEAVED:
+ if (phys_bank != BANK_NONE)
+ {
+ mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
+ mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
+ mem_mapping_set_addr(&scamp.ram_mapping[bank_nr], 0x100000, 0xf00000);
+ mem_mapping_set_exec(&scamp.ram_mapping[bank_nr], &ram[scamp.ram_phys_base[bank_nr] + 0x100000]);
+ }
+ virt_base += 8192*1024*2;
+ scamp.row_virt_shift[bank_nr] = 12;
+ break;
+ }
+ }
+ else
+ {
+ switch (rammap[cur_rammap].bank[bank_nr])
+ {
+ case BANK_NONE:
+ break;
+
+ case BANK_256K:
+ if (phys_bank != BANK_NONE)
+ {
+ mem_mapping_set_addr(&scamp.ram_mapping[bank_nr], virt_base, 0x80000);
+ mem_mapping_set_exec(&scamp.ram_mapping[bank_nr], &ram[scamp.ram_phys_base[bank_nr]]);
+ }
+ virt_base += 512*1024;
+ scamp.row_virt_shift[bank_nr] = 10;
+ break;
+
+ case BANK_256K_INTERLEAVED:
+ if (phys_bank != BANK_NONE)
+ {
+ mem_mapping_set_addr(&scamp.ram_mapping[bank_nr], virt_base, 0x100000);
+ mem_mapping_set_exec(&scamp.ram_mapping[bank_nr], &ram[scamp.ram_phys_base[bank_nr]]);
+ }
+ virt_base += 512*1024*2;
+ scamp.row_virt_shift[bank_nr] = 10;
+ break;
+
+ case BANK_1M:
+ if (phys_bank != BANK_NONE)
+ {
+ mem_mapping_set_addr(&scamp.ram_mapping[bank_nr], virt_base, 0x200000);
+ mem_mapping_set_exec(&scamp.ram_mapping[bank_nr], &ram[scamp.ram_phys_base[bank_nr]]);
+ }
+ virt_base += 2048*1024;
+ scamp.row_virt_shift[bank_nr] = 11;
+ break;
+
+ case BANK_1M_INTERLEAVED:
+ if (phys_bank != BANK_NONE)
+ {
+ mem_mapping_set_addr(&scamp.ram_mapping[bank_nr], virt_base, 0x400000);
+ mem_mapping_set_exec(&scamp.ram_mapping[bank_nr], &ram[scamp.ram_phys_base[bank_nr]]);
+ }
+ virt_base += 2048*1024*2;
+ scamp.row_virt_shift[bank_nr] = 11;
+ break;
+
+ case BANK_4M:
+ if (phys_bank != BANK_NONE)
+ {
+ mem_mapping_set_addr(&scamp.ram_mapping[bank_nr], virt_base, 0x800000);
+ mem_mapping_set_exec(&scamp.ram_mapping[bank_nr], &ram[scamp.ram_phys_base[bank_nr]]);
+ }
+ virt_base += 8192*1024;
+ scamp.row_virt_shift[bank_nr] = 12;
+ break;
+
+ case BANK_4M_INTERLEAVED:
+ if (phys_bank != BANK_NONE)
+ {
+ mem_mapping_set_addr(&scamp.ram_mapping[bank_nr], virt_base, 0x1000000);
+ mem_mapping_set_exec(&scamp.ram_mapping[bank_nr], &ram[scamp.ram_phys_base[bank_nr]]);
+ }
+ virt_base += 8192*1024*2;
+ scamp.row_virt_shift[bank_nr] = 12;
+ break;
+ }
+ }
+ switch (rammap[cur_rammap].bank[bank_nr])
+ {
+ case BANK_256K: case BANK_1M: case BANK_4M:
+ mem_mapping_set_handler(&scamp.ram_mapping[bank_nr],
+ ram_mirrored_read, NULL, NULL,
+ ram_mirrored_write, NULL, NULL);
+ if (!old_virt_base)
+ mem_mapping_set_handler(&ram_low_mapping,
+ ram_mirrored_read, NULL, NULL,
+ ram_mirrored_write, NULL, NULL);
+ pclog(" not interleaved\n");
+ break;
+
+ case BANK_256K_INTERLEAVED: case BANK_1M_INTERLEAVED:
+ mem_mapping_set_handler(&scamp.ram_mapping[bank_nr],
+ ram_mirrored_interleaved_read, NULL, NULL,
+ ram_mirrored_interleaved_write, NULL, NULL);
+ if (!old_virt_base)
+ mem_mapping_set_handler(&ram_low_mapping,
+ ram_mirrored_interleaved_read, NULL, NULL,
+ ram_mirrored_interleaved_write, NULL, NULL);
+ pclog(" interleaved\n");
+ break;
+
+ case BANK_4M_INTERLEAVED:
+ if (phys_bank == BANK_256K || phys_bank == BANK_256K_INTERLEAVED)
+ {
+ mem_mapping_set_handler(&scamp.ram_mapping[bank_nr],
+ ram_mirrored_256k_in_4mi_read, NULL, NULL,
+ ram_mirrored_256k_in_4mi_write, NULL, NULL);
+ if (!old_virt_base)
+ mem_mapping_set_handler(&ram_low_mapping,
+ ram_mirrored_256k_in_4mi_read, NULL, NULL,
+ ram_mirrored_256k_in_4mi_write, NULL, NULL);
+ pclog(" 256k in 4mi\n");
+ }
+ else
+ {
+ mem_mapping_set_handler(&scamp.ram_mapping[bank_nr],
+ ram_mirrored_interleaved_read, NULL, NULL,
+ ram_mirrored_interleaved_write, NULL, NULL);
+ if (!old_virt_base)
+ mem_mapping_set_handler(&ram_low_mapping,
+ ram_mirrored_interleaved_read, NULL, NULL,
+ ram_mirrored_interleaved_write, NULL, NULL);
+ pclog(" interleaved\n");
+ }
+ break;
+ }
+ }
+}
+
+#define NR_ELEMS(x) (sizeof(x) / sizeof(x[0]))
+
+static void shadow_control(uint32_t addr, uint32_t size, int state)
+{
+// pclog("shadow_control: addr=%08x size=%04x state=%i\n", addr, size, state);
+ switch (state)
+ {
+ case 0:
+ mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 1:
+ mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ case 2:
+ mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 3:
+ mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ }
+ flushmmucache_nopc();
+}
+
+void scamp_write(uint16_t addr, uint8_t val, void *p)
+{
+// pclog("scamp_write: addr=%04x val=%02x\n", addr, val);
+ switch (addr)
+ {
+ case 0x92:
+ if ((mem_a20_alt ^ val) & 2)
+ {
+ mem_a20_alt = val & 2;
+ mem_a20_recalc();
+ }
+ if ((~scamp.port_92 & val) & 1)
+ {
+ softresetx86();
+ cpu_set_edx();
+ }
+ scamp.port_92 = val;
+ break;
+
+ case 0xec:
+ if (scamp.cfg_enable)
+ scamp.cfg_index = val;
+ break;
+
+ case 0xed:
+ if (scamp.cfg_enable)
+ {
+ if (scamp.cfg_index >= 0x02 && scamp.cfg_index <= 0x16)
+ {
+ scamp.cfg_regs[scamp.cfg_index] = val;
+// pclog("SCAMP CFG[%02x]=%02x\n", scamp.cfg_index, val);
+ switch (scamp.cfg_index)
+ {
+ case CFG_SLTPTR:
+ break;
+
+ case CFG_RAMMAP:
+ recalc_mappings();
+ mem_mapping_disable(&ram_remapped_mapping);
+ if (scamp.cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)
+ {
+ /*Enabling remapping will disable all shadowing*/
+ mem_remap_top_384k();
+ shadow_control(0xa0000, 0x60000, 0);
+ }
+ else
+ {
+ shadow_control(0xa0000, 0x8000, scamp.cfg_regs[CFG_ABAXS] & 3);
+ shadow_control(0xa8000, 0x8000, (scamp.cfg_regs[CFG_ABAXS] >> 2) & 3);
+ shadow_control(0xb0000, 0x8000, (scamp.cfg_regs[CFG_ABAXS] >> 4) & 3);
+ shadow_control(0xb8000, 0x8000, (scamp.cfg_regs[CFG_ABAXS] >> 6) & 3);
+
+ shadow_control(0xc0000, 0x4000, scamp.cfg_regs[CFG_CAXS] & 3);
+ shadow_control(0xc4000, 0x4000, (scamp.cfg_regs[CFG_CAXS] >> 2) & 3);
+ shadow_control(0xc8000, 0x4000, (scamp.cfg_regs[CFG_CAXS] >> 4) & 3);
+ shadow_control(0xcc000, 0x4000, (scamp.cfg_regs[CFG_CAXS] >> 6) & 3);
+
+ shadow_control(0xd0000, 0x4000, scamp.cfg_regs[CFG_DAXS] & 3);
+ shadow_control(0xd4000, 0x4000, (scamp.cfg_regs[CFG_DAXS] >> 2) & 3);
+ shadow_control(0xd8000, 0x4000, (scamp.cfg_regs[CFG_DAXS] >> 4) & 3);
+ shadow_control(0xdc000, 0x4000, (scamp.cfg_regs[CFG_DAXS] >> 6) & 3);
+
+ shadow_control(0xe0000, 0x8000, scamp.cfg_regs[CFG_FEAXS] & 3);
+ shadow_control(0xe8000, 0x8000, (scamp.cfg_regs[CFG_FEAXS] >> 2) & 3);
+ shadow_control(0xf0000, 0x8000, (scamp.cfg_regs[CFG_FEAXS] >> 4) & 3);
+ shadow_control(0xf8000, 0x8000, (scamp.cfg_regs[CFG_FEAXS] >> 6) & 3);
+ }
+ break;
+
+ case CFG_ABAXS:
+ if (!(scamp.cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386))
+ {
+ shadow_control(0xa0000, 0x8000, val & 3);
+ shadow_control(0xa8000, 0x8000, (val >> 2) & 3);
+ shadow_control(0xb0000, 0x8000, (val >> 4) & 3);
+ shadow_control(0xb8000, 0x8000, (val >> 6) & 3);
+ }
+ break;
+
+ case CFG_CAXS:
+ if (!(scamp.cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386))
+ {
+ shadow_control(0xc0000, 0x4000, val & 3);
+ shadow_control(0xc4000, 0x4000, (val >> 2) & 3);
+ shadow_control(0xc8000, 0x4000, (val >> 4) & 3);
+ shadow_control(0xcc000, 0x4000, (val >> 6) & 3);
+ }
+ break;
+
+ case CFG_DAXS:
+ if (!(scamp.cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386))
+ {
+ shadow_control(0xd0000, 0x4000, val & 3);
+ shadow_control(0xd4000, 0x4000, (val >> 2) & 3);
+ shadow_control(0xd8000, 0x4000, (val >> 4) & 3);
+ shadow_control(0xdc000, 0x4000, (val >> 6) & 3);
+ }
+ break;
+
+ case CFG_FEAXS:
+ if (!(scamp.cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386))
+ {
+ shadow_control(0xe0000, 0x8000, val & 3);
+ shadow_control(0xe8000, 0x8000, (val >> 2) & 3);
+ shadow_control(0xf0000, 0x8000, (val >> 4) & 3);
+ shadow_control(0xf8000, 0x8000, (val >> 6) & 3);
+ }
+ break;
+ }
+ }
+ }
+ break;
+
+ case 0xee:
+ if (scamp.cfg_enable && mem_a20_alt)
+ {
+ scamp.port_92 &= ~2;
+ mem_a20_alt = 0;
+ mem_a20_recalc();
+ }
+ break;
+ }
+}
+
+uint8_t scamp_read(uint16_t addr, void *p)
+{
+ uint8_t ret = 0xff;
+
+ switch (addr)
+ {
+ case 0x92:
+ ret = scamp.port_92;
+ break;
+
+ case 0xed:
+ if (scamp.cfg_enable)
+ {
+ if (scamp.cfg_index >= 0x00 && scamp.cfg_index <= 0x16)
+ ret = scamp.cfg_regs[scamp.cfg_index];
+ }
+ break;
+
+ case 0xee:
+ if (!mem_a20_alt)
+ {
+ scamp.port_92 |= 2;
+ mem_a20_alt = 1;
+ mem_a20_recalc();
+ }
+ break;
+
+ case 0xef:
+ softresetx86();
+ cpu_set_edx();
+ break;
+ }
+
+// pclog("scamp_read: addr=%04x ret=%02x\n", addr, ret);
+ return ret;
+}
+
+void scamp_init(void)
+{
+ uint32_t addr;
+ intptr_t c;
+
+ memset(&scamp, 0, sizeof(scamp));
+ scamp.cfg_regs[CFG_ID] = ID_VL82C311;
+ scamp.cfg_enable = 1;
+
+ io_sethandler(0x0092, 0x0001, scamp_read, NULL, NULL, scamp_write, NULL, NULL, NULL);
+ io_sethandler(0x00e8, 0x0001, scamp_read, NULL, NULL, scamp_write, NULL, NULL, NULL);
+ io_sethandler(0x00ea, 0x0006, scamp_read, NULL, NULL, scamp_write, NULL, NULL, NULL);
+ io_sethandler(0x00f4, 0x0002, scamp_read, NULL, NULL, scamp_write, NULL, NULL, NULL);
+ io_sethandler(0x00f9, 0x0001, scamp_read, NULL, NULL, scamp_write, NULL, NULL, NULL);
+ io_sethandler(0x00fb, 0x0001, scamp_read, NULL, NULL, scamp_write, NULL, NULL, NULL);
+
+ scamp.ram_config = 0;
+
+ /*Find best fit configuration for the requested memory size*/
+ for (c = 0; c < NR_ELEMS(ram_configs); c++)
+ {
+ if (mem_size < ram_configs[c].size_kb)
+ break;
+
+ scamp.ram_config = c;
+ }
+
+ mem_mapping_set_handler(&ram_low_mapping,
+ ram_mirrored_read, NULL, NULL,
+ ram_mirrored_write, NULL, NULL);
+ mem_mapping_disable(&ram_high_mapping);
+
+ addr = 0;
+ for (c = 0; c < 2; c++)
+ {
+ mem_mapping_add(&scamp.ram_mapping[c], 0, 0,
+ ram_mirrored_read, NULL, NULL,
+ ram_mirrored_write, NULL, NULL,
+ &ram[addr], MEM_MAPPING_INTERNAL, (void *)c);
+ mem_mapping_disable(&scamp.ram_mapping[c]);
+
+ scamp.ram_phys_base[c] = addr;
+// pclog("Bank calc : %i = %08x\n", c ,addr);
+
+ switch (ram_configs[scamp.ram_config].bank[c])
+ {
+ case BANK_NONE:
+ scamp.ram_mask[c] = 0;
+ scamp.ram_interleaved[c] = 0;
+ break;
+
+ case BANK_256K:
+ addr += 512*1024;
+ scamp.ram_mask[c] = 0x1ff;
+ scamp.row_phys_shift[c] = 10;
+ scamp.ram_interleaved[c] = 0;
+ break;
+
+ case BANK_256K_INTERLEAVED:
+ addr += 512*1024*2;
+ scamp.ram_mask[c] = 0x1ff;
+ scamp.row_phys_shift[c] = 10;
+ scamp.ibank_shift[c] = 19;
+ scamp.ram_interleaved[c] = 1;
+ break;
+
+ case BANK_1M:
+ addr += 2048*1024;
+ scamp.ram_mask[c] = 0x3ff;
+ scamp.row_phys_shift[c] = 11;
+ scamp.ram_interleaved[c] = 0;
+ break;
+
+ case BANK_1M_INTERLEAVED:
+ addr += 2048*1024*2;
+ scamp.ram_mask[c] = 0x3ff;
+ scamp.row_phys_shift[c] = 11;
+ scamp.ibank_shift[c] = 21;
+ scamp.ram_interleaved[c] = 1;
+ break;
+
+ case BANK_4M:
+ addr += 8192*1024;
+ scamp.ram_mask[c] = 0x7ff;
+ scamp.row_phys_shift[c] = 12;
+ scamp.ram_interleaved[c] = 0;
+ break;
+
+ case BANK_4M_INTERLEAVED:
+ addr += 8192*1024*2;
+ scamp.ram_mask[c] = 0x7ff;
+ scamp.row_phys_shift[c] = 12;
+ scamp.ibank_shift[c] = 23;
+ scamp.ram_interleaved[c] = 1;
+ break;
+ }
+ }
+
+ mem_set_mem_state(0xfe0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+}
diff --git a/src/scamp.h b/src/scamp.h
new file mode 100644
index 0000000..a4785ca
--- /dev/null
+++ b/src/scamp.h
@@ -0,0 +1 @@
+void scamp_init(void);
diff --git a/src/scat.c b/src/scat.c
index a899b95..ca33af5 100644
--- a/src/scat.c
+++ b/src/scat.c
@@ -11,48 +11,86 @@ static uint8_t scat_regs[256];
static int scat_index;
static uint8_t scat_port_92 = 0;
static uint8_t scat_ems_reg_2xA = 0;
-static mem_mapping_t scat_mapping[32];
+static mem_mapping_t scat_low_mapping[32];
+static mem_mapping_t scat_ems_mapping[32];
static mem_mapping_t scat_high_mapping[16];
static scat_t scat_stat[32];
static uint32_t scat_xms_bound;
-static mem_mapping_t scat_shadowram_mapping[6];
-static mem_mapping_t scat_4000_9FFF_mapping[24];
-static mem_mapping_t scat_A000_BFFF_mapping;
+static mem_mapping_t scat_remap_mapping[6];
+static mem_mapping_t scat_4000_EFFF_mapping[44];
+static mem_mapping_t scat_low_ROMCS_mapping[8];
-// TODO - 82C836 chipset's memory address mapping isn't fully implemented yet, so memory configuration is hardcoded now.
-static int scatsx_mem_conf_val[33] = { 0x00, 0x01, 0x03, 0x04, 0x05, 0x08, 0x06, 0x06,
- 0x0c, 0x09, 0x07, 0x07, 0x0d, 0x0a, 0x0f, 0x0f,
- 0x0e, 0x0e, 0x10, 0x10, 0x13, 0x13, 0x11, 0x11,
- 0x14, 0x14, 0x12, 0x12, 0x15, 0x15, 0x15, 0x15,
- 0x16 };
+static int scat_max_map[32] = { 0, 1, 1, 1, 2, 3, 4, 8,
+ 4, 8, 12, 16, 20, 24, 28, 32,
+ 0, 5, 9, 13, 6, 10, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 };
+static int scatsx_max_map[32] = { 0, 1, 2, 1, 3, 4, 6, 10,
+ 5, 9, 13, 4, 8, 12, 16, 14,
+ 18, 22, 26, 20, 24, 28, 32, 18,
+ 20, 32, 0, 0, 0, 0, 0, 0 };
+
+static int external_is_RAS = 0;
+
+static int scatsx_external_is_RAS[33] = { 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0 };
uint8_t scat_read(uint16_t port, void *priv);
void scat_write(uint16_t port, uint8_t val, void *priv);
+void scat_romcs_state_update(uint8_t val)
+{
+ int i;
+ for(i = 0; i < 4; i++)
+ {
+ if (val & 1)
+ {
+ mem_mapping_enable(&scat_low_ROMCS_mapping[i << 1]);
+ mem_mapping_enable(&scat_low_ROMCS_mapping[(i << 1) + 1]);
+ }
+ else
+ {
+ mem_mapping_disable(&scat_low_ROMCS_mapping[i << 1]);
+ mem_mapping_disable(&scat_low_ROMCS_mapping[(i << 1) + 1]);
+ }
+ val >>= 1;
+ }
+
+ for(i = 0; i < 4; i++)
+ {
+ if (val & 1)
+ {
+ mem_mapping_enable(&bios_mapping[i << 1]);
+ mem_mapping_enable(&bios_mapping[(i << 1) + 1]);
+ }
+ else
+ {
+ mem_mapping_disable(&bios_mapping[i << 1]);
+ mem_mapping_disable(&bios_mapping[(i << 1) + 1]);
+ }
+ val >>= 1;
+ }
+}
+
void scat_shadow_state_update()
{
int i, val;
- // TODO - ROMCS enable features should be implemented later.
- for (i = 0; i < 24; i++)
+ if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) < 4)
{
- val = ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTERNAL;
- if (i < 8)
+ /*Less than 1MB low memory, no shadow RAM available*/
+ for (i = 0; i < 24; i++)
+ mem_set_mem_state((i + 40) << 14, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ }
+ else
+ {
+ for (i = 0; i < 24; i++)
{
- val |= ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTERNAL;
+ val = ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_READ_INTERNAL | MEM_WRITE_INTERNAL : MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL;
+ mem_set_mem_state((i + 40) << 14, 0x4000, val);
}
- else
- {
- if ((scat_regs[SCAT_RAM_WRITE_PROTECT] >> ((i - 8) >> 1)) & 1)
- {
- val |= MEM_WRITE_DISABLED;
- }
- else
- {
- val |= ((scat_regs[SCAT_SHADOW_RAM_ENABLE_1 + (i >> 3)] >> (i & 7)) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTERNAL;
- }
- }
- mem_set_mem_state((i + 40) << 14, 0x4000, val);
}
flushmmucache();
@@ -60,8 +98,7 @@ void scat_shadow_state_update()
void scat_set_xms_bound(uint8_t val)
{
- uint32_t max_xms_size = (mem_size >= 16128) ? (((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) ? 0xFE0000 : 0xFC0000) : mem_size << 10;
- int i;
+ uint32_t max_xms_size = ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) || (scat_regs[SCAT_VERSION] >= 4) ? 0xFE0000 : 0xFC0000;
switch (val & 0x0F)
{
@@ -117,21 +154,9 @@ void scat_set_xms_bound(uint8_t val)
if ((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (val & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3))
{
- if (val != 1)
- {
- if(mem_size > 1024) mem_mapping_disable(&ram_high_mapping);
- for(i=0;i<6;i++)
- mem_mapping_enable(&scat_shadowram_mapping[i]);
- if ((val & 0x0F) == 0)
- scat_xms_bound = 0x160000;
- }
- else
- {
- for(i=0;i<6;i++)
- mem_mapping_disable(&scat_shadowram_mapping[i]);
- if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping);
- }
- pclog("Set XMS bound(%02X) = %06X(%dKbytes for EMS access)\n", val, scat_xms_bound, (0x160000 - scat_xms_bound) >> 10);
+ if((val & 0x0F) == 0 || scat_xms_bound > 0x160000)
+ scat_xms_bound = 0x160000;
+// pclog("Set XMS bound(%02X) = %06X(%dKbytes for EMS access)\n", val, scat_xms_bound, (0x160000 - scat_xms_bound) >> 10);
if (scat_xms_bound > 0x100000)
mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
if (scat_xms_bound < 0x160000)
@@ -139,68 +164,721 @@ void scat_set_xms_bound(uint8_t val)
}
else
{
- for(i=0;i<6;i++)
- mem_mapping_disable(&scat_shadowram_mapping[i]);
- if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping);
-
if (scat_xms_bound > max_xms_size)
scat_xms_bound = max_xms_size;
- pclog("Set XMS bound(%02X) = %06X(%dKbytes for EMS access)\n", val, scat_xms_bound, ((mem_size << 10) - scat_xms_bound) >> 10);
+// pclog("Set XMS bound(%02X) = %06X(%dKbytes for EMS access)\n", val, scat_xms_bound, ((mem_size << 10) - scat_xms_bound) >> 10);
if (scat_xms_bound > 0x100000)
mem_set_mem_state(0x100000, scat_xms_bound - 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
if (scat_xms_bound < (mem_size << 10))
mem_set_mem_state(scat_xms_bound, (mem_size << 10) - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
+
+ mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) || (scat_regs[SCAT_VERSION] >= 4) ? 0x60000 : 0x40000);
+ if(scat_regs[SCAT_VERSION] & 0xF0)
+ {
+ int i;
+ for(i=0;i<8;i++)
+ {
+ if(val & 0x10)
+ mem_mapping_disable(&scat_high_mapping[i]);
+ else
+ mem_mapping_enable(&scat_high_mapping[i]);
+ }
+ }
}
uint32_t get_scat_addr(uint32_t addr, scat_t *p)
{
+ int nbank;
+
if (p && (scat_regs[SCAT_EMS_CONTROL] & 0x80) && (p->regs_2x9 & 0x80))
addr = (addr & 0x3fff) | (((p->regs_2x9 & 3) << 8) | p->regs_2x8) << 14;
if ((scat_regs[SCAT_VERSION] & 0xF0) == 0)
{
- if (mem_size < 2048 && ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) > 7 || (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) != 0))
- addr = (addr & ~0x780000) | ((addr & 0x600000) >> 2);
- else if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8 && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0)
+ switch((scat_regs[SCAT_EXTENDED_BOUNDARY] & ((scat_regs[SCAT_VERSION] & 0x0F) > 3 ? 0x40 : 0)) | (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F))
{
- addr &= ~0x600000;
- if(mem_size > 2048 || (mem_size == 2048 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 6))
- addr |= (addr & 0x180000) << 2;
+ case 0x41:
+ nbank = addr >> 19;
+ if(nbank < 4)
+ nbank = 1;
+ else if(nbank == 4)
+ nbank = 0;
+ else
+ nbank -= 3;
+ break;
+ case 0x42:
+ nbank = addr >> 19;
+ if(nbank < 8)
+ nbank = 1 + (nbank >> 2);
+ else if(nbank == 8)
+ nbank = 0;
+ else
+ nbank -= 6;
+ break;
+ case 0x43:
+ nbank = addr >> 19;
+ if(nbank < 12)
+ nbank = 1 + (nbank >> 2);
+ else if(nbank == 12)
+ nbank = 0;
+ else
+ nbank -= 9;
+ break;
+ case 0x44:
+ nbank = addr >> 19;
+ if(nbank < 4)
+ nbank = 2;
+ else if(nbank < 6)
+ nbank -= 4;
+ else
+ nbank -= 3;
+ break;
+ case 0x45:
+ nbank = addr >> 19;
+ if(nbank < 8)
+ nbank = 2 + (nbank >> 2);
+ else if(nbank < 10)
+ nbank -= 8;
+ else
+ nbank -= 6;
+ break;
+ default:
+ nbank = addr >> (((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8 && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) ? 19 : 21);
+ break;
+ }
+ nbank &= (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3;
+ if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3 && nbank == 2 && (addr & 0x7FFFF) < 0x60000 && mem_size > 640)
+ {
+ nbank = 1;
+ addr ^= 0x70000;
}
- if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3 && (addr & ~0x600000) >= 0x100000 && (addr & ~0x600000) < 0x160000)
- addr ^= mem_size < 2048 ? 0x1F0000 : 0x670000;
+ if(external_is_RAS && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0)
+ {
+ if(nbank == 3)
+ nbank = 7;
+ else
+ return 0xFFFFFFFF;
+ }
+ else if(!external_is_RAS && scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80)
+ {
+ switch(nbank)
+ {
+ case 7:
+ nbank = 3;
+ break;
+ // Note - In the following cases, the chipset accesses multiple memory banks at the same time, so it's impossible to predict which memory bank is actually accessed.
+ case 5:
+ case 1:
+ nbank = 1;
+ break;
+ case 3:
+ nbank = 2;
+ break;
+ default:
+ nbank = 0;
+ break;
+ }
+ }
+
+ if((scat_regs[SCAT_VERSION] & 0x0F) > 3 && (mem_size > 2048) && (mem_size & 1536))
+ {
+ if((mem_size & 1536) == 512)
+ {
+ if(nbank == 0)
+ addr &= 0x7FFFF;
+ else
+ addr = 0x80000 + ((addr & 0x1FFFFF) | ((nbank - 1) << 21));
+ }
+ else
+ {
+ if(nbank < 2)
+ addr = (addr & 0x7FFFF) | (nbank << 19);
+ else
+ addr = 0x100000 + ((addr & 0x1FFFFF) | ((nbank - 2) << 21));
+ }
+ }
+ else
+ {
+ int nbanks_2048k, nbanks_512k;
+ if (mem_size <= ((scat_regs[SCAT_VERSION] & 0x0F) > 3 ? 2048 : 4096) && (((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8) || external_is_RAS))
+ {
+ nbanks_2048k = 0;
+ nbanks_512k = mem_size >> 9;
+ }
+ else
+ {
+ nbanks_2048k = mem_size >> 11;
+ nbanks_512k = (mem_size & 1536) >> 9;
+ }
+ if(nbank < nbanks_2048k || (nbanks_2048k > 0 && nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7)))
+ {
+ addr &= 0x1FFFFF;
+ addr |= (nbank << 21);
+ }
+ else if(nbank < nbanks_2048k + nbanks_512k || nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7))
+ {
+ addr &= 0x7FFFF;
+ addr |= (nbanks_2048k << 21) | ((nbank - nbanks_2048k) << 19);
+ }
+ else
+ {
+ addr &= 0x1FFFF;
+ addr |= (nbanks_2048k << 21) | (nbanks_512k << 19) | ((nbank - nbanks_2048k - nbanks_512k) << 17);
+ }
+ }
}
else
{
- if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3 && (addr & ~0x600000) >= 0x100000 && (addr & ~0x600000) < 0x160000)
- addr ^= 0x1F0000;
+ uint32_t addr2;
+ switch(scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F)
+ {
+ case 2:
+ case 4:
+ nbank = addr >> 19;
+ if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2)
+ {
+ nbank = (addr >> 10) & 1;
+ addr2 = addr >> 11;
+ }
+ else
+ addr2 = addr >> 10;
+ break;
+ case 3:
+ nbank = addr >> 19;
+ if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2)
+ {
+ nbank = (addr >> 10) & 1;
+ addr2 = addr >> 11;
+ }
+ else if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) == 2 && (addr & 0x7FFFF) < 0x60000)
+ {
+ addr ^= 0x1F0000;
+ nbank = (addr >> 10) & 1;
+ addr2 = addr >> 11;
+ }
+ else
+ addr2 = addr >> 10;
+ break;
+ case 5:
+ nbank = addr >> 19;
+ if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4)
+ {
+ nbank = (addr >> 10) & 3;
+ addr2 = addr >> 12;
+ }
+ else
+ addr2 = addr >> 10;
+ break;
+ case 6:
+ nbank = addr >> 19;
+ if(nbank < 2)
+ {
+ nbank = (addr >> 10) & 1;
+ addr2 = addr >> 11;
+ }
+ else
+ {
+ nbank = 2 + ((addr - 0x100000) >> 21);
+ addr2 = (addr - 0x100000) >> 11;
+ }
+ break;
+ case 7:
+ case 0x0F:
+ nbank = addr >> 19;
+ if(nbank < 2)
+ {
+ nbank = (addr >> 10) & 1;
+ addr2 = addr >> 11;
+ }
+ else if(nbank < 10)
+ {
+ nbank = 2 + (((addr - 0x100000) >> 11) & 1);
+ addr2 = (addr - 0x100000) >> 12;
+ }
+ else
+ {
+ nbank = 4 + ((addr - 0x500000) >> 21);
+ addr2 = (addr - 0x500000) >> 11;
+ }
+ break;
+ case 8:
+ nbank = addr >> 19;
+ if(nbank < 4)
+ {
+ nbank = 1;
+ addr2 = addr >> 11;
+ }
+ else if(nbank == 4)
+ {
+ nbank = 0;
+ addr2 = addr >> 10;
+ }
+ else
+ {
+ nbank -= 3;
+ addr2 = addr >> 10;
+ }
+ break;
+ case 9:
+ nbank = addr >> 19;
+ if(nbank < 8)
+ {
+ nbank = 1 + ((addr >> 11) & 1);
+ addr2 = addr >> 12;
+ }
+ else if(nbank == 8)
+ {
+ nbank = 0;
+ addr2 = addr >> 10;
+ }
+ else
+ {
+ nbank -= 6;
+ addr2 = addr >> 10;
+ }
+ break;
+ case 0x0A:
+ nbank = addr >> 19;
+ if(nbank < 8)
+ {
+ nbank = 1 + ((addr >> 11) & 1);
+ addr2 = addr >> 12;
+ }
+ else if(nbank < 12)
+ {
+ nbank = 3;
+ addr2 = addr >> 11;
+ }
+ else if(nbank == 12)
+ {
+ nbank = 0;
+ addr2 = addr >> 10;
+ }
+ else
+ {
+ nbank -= 9;
+ addr2 = addr >> 10;
+ }
+ break;
+ case 0x0B:
+ nbank = addr >> 21;
+ addr2 = addr >> 11;
+ break;
+ case 0x0C:
+ case 0x0D:
+ nbank = addr >> 21;
+ if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2)
+ {
+ nbank = (addr >> 11) & 1;
+ addr2 = addr >> 12;
+ }
+ else
+ addr2 = addr >> 11;
+ break;
+ case 0x0E:
+ case 0x13:
+ nbank = addr >> 21;
+ if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4)
+ {
+ nbank = (addr >> 11) & 3;
+ addr2 = addr >> 13;
+ }
+ else
+ addr2 = addr >> 11;
+ break;
+ case 0x10:
+ case 0x11:
+ nbank = addr >> 19;
+ if(nbank < 2)
+ {
+ nbank = (addr >> 10) & 1;
+ addr2 = addr >> 11;
+ }
+ else if(nbank < 10)
+ {
+ nbank = 2 + (((addr - 0x100000) >> 11) & 1);
+ addr2 = (addr - 0x100000) >> 12;
+ }
+ else if(nbank < 18)
+ {
+ nbank = 4 + (((addr - 0x500000) >> 11) & 1);
+ addr2 = (addr - 0x500000) >> 12;
+ }
+ else
+ {
+ nbank = 6 + ((addr - 0x900000) >> 21);
+ addr2 = (addr - 0x900000) >> 11;
+ }
+ break;
+ case 0x12:
+ nbank = addr >> 19;
+ if(nbank < 2)
+ {
+ nbank = (addr >> 10) & 1;
+ addr2 = addr >> 11;
+ }
+ else if(nbank < 10)
+ {
+ nbank = 2 + (((addr - 0x100000) >> 11) & 1);
+ addr2 = (addr - 0x100000) >> 12;
+ }
+ else
+ {
+ nbank = 4 + (((addr - 0x500000) >> 11) & 3);
+ addr2 = (addr - 0x500000) >> 13;
+ }
+ break;
+ case 0x14:
+ case 0x15:
+ nbank = addr >> 21;
+ if((nbank & 7) < 4)
+ {
+ nbank = (addr >> 11) & 3;
+ addr2 = addr >> 13;
+ }
+ else if((nbank & 7) < 6)
+ {
+ nbank = 4 + (((addr - 0x800000) >> 11) & 1);
+ addr2 = (addr - 0x800000) >> 12;
+ }
+ else
+ {
+ nbank = 6 + (((addr - 0xC00000) >> 11) & 3);
+ addr2 = (addr - 0xC00000) >> 13;
+ }
+ break;
+ case 0x16:
+ nbank = ((addr >> 21) & 4) | ((addr >> 11) & 3);
+ addr2 = addr >> 13;
+ break;
+ case 0x17:
+ if(external_is_RAS && (addr & 0x800) == 0)
+ return 0xFFFFFFFF;
+ nbank = addr >> 19;
+ if(nbank < 2)
+ {
+ nbank = (addr >> 10) & 1;
+ addr2 = addr >> 11;
+ }
+ else
+ {
+ nbank = 2 + ((addr - 0x100000) >> 23);
+ addr2 = (addr - 0x100000) >> 12;
+ }
+ break;
+ case 0x18:
+ if(external_is_RAS && (addr & 0x800) == 0)
+ return 0xFFFFFFFF;
+ nbank = addr >> 21;
+ if(nbank < 4)
+ {
+ nbank = 1;
+ addr2 = addr >> 12;
+ }
+ else if(nbank == 4)
+ {
+ nbank = 0;
+ addr2 = addr >> 11;
+ }
+ else
+ {
+ nbank -= 3;
+ addr2 = addr >> 11;
+ }
+ break;
+ case 0x19:
+ if(external_is_RAS && (addr & 0x800) == 0)
+ return 0xFFFFFFFF;
+ nbank = addr >> 23;
+ if((nbank & 3) < 2)
+ {
+ nbank = (addr >> 12) & 1;
+ addr2 = addr >> 13;
+ }
+ else
+ addr2 = addr >> 12;
+ break;
+ default:
+ if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 6)
+ {
+ nbank = addr >> 19;
+ addr2 = (addr >> 10) & 0x1FF;
+ }
+ else if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 0x17)
+ {
+ nbank = addr >> 21;
+ addr2 = (addr >> 11) & 0x3FF;
+ }
+ else
+ {
+ nbank = addr >> 23;
+ addr2 = (addr >> 12) & 0x7FF;
+ }
+ break;
+ }
+
+ nbank &= (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3;
+ if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) > 0x16 && nbank == 3)
+ return 0xFFFFFFFF;
+
+ if(external_is_RAS && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0)
+ {
+ if(nbank == 3)
+ nbank = 7;
+ else
+ return 0xFFFFFFFF;
+ }
+ else if(!external_is_RAS && scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80)
+ {
+ switch(nbank)
+ {
+ case 7:
+ nbank = 3;
+ break;
+ // Note - In the following cases, the chipset accesses multiple memory banks at the same time, so it's impossible to predict which memory bank is actually accessed.
+ case 5:
+ case 1:
+ nbank = 1;
+ break;
+ case 3:
+ nbank = 2;
+ break;
+ default:
+ nbank = 0;
+ break;
+ }
+ }
+
+ switch(mem_size & ~511)
+ {
+ case 1024:
+ case 1536:
+ addr &= 0x3FF;
+ if(nbank < 2)
+ addr |= (nbank << 10) | ((addr2 & 0x1FF) << 11);
+ else
+ addr |= ((addr2 & 0x1FF) << 10) | (nbank << 19);
+ break;
+ case 2048:
+ if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 5)
+ {
+ addr &= 0x3FF;
+ if(nbank < 4)
+ addr |= (nbank << 10) | ((addr2 & 0x1FF) << 12);
+ else
+ addr |= ((addr2 & 0x1FF) << 10) | (nbank << 19);
+ }
+ else
+ {
+ addr &= 0x7FF;
+ addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
+ }
+ break;
+ case 2560:
+ if(nbank == 0)
+ addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
+ else
+ {
+ addr &= 0x7FF;
+ addr2 &= 0x3FF;
+ addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21));
+ }
+ break;
+ case 3072:
+ if(nbank < 2)
+ addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
+ else
+ addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21));
+ break;
+ case 4096:
+ case 6144:
+ addr &= 0x7FF;
+ if(nbank < 2)
+ addr |= (nbank << 11) | ((addr2 & 0x3FF) << 12);
+ else
+ addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
+ break;
+ case 4608:
+ if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) >= 8 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) <= 0x0A) || ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 0x18))
+ {
+ if(nbank == 0)
+ addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
+ else if(nbank < 3)
+ addr = 0x80000 + ((addr & 0x7FF) | ((nbank - 1) << 11) | ((addr2 & 0x3FF) << 12));
+ else
+ addr = 0x480000 + ((addr & 0x3FF) | ((addr2 & 0x1FF) << 10) | ((nbank - 3) << 19));
+ }
+ else if(nbank == 0)
+ addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
+ else
+ {
+ addr &= 0x7FF;
+ addr2 &= 0x3FF;
+ addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21));
+ }
+ break;
+ case 5120:
+ case 7168:
+ if(nbank < 2)
+ addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
+ else if(nbank < 4)
+ addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11));
+ else
+ addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21));
+ break;
+ case 6656:
+ if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) >= 8 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) <= 0x0A) || ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 0x18))
+ {
+ if(nbank == 0)
+ addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
+ else if(nbank < 3)
+ addr = 0x80000 + ((addr & 0x7FF) | ((nbank - 1) << 11) | ((addr2 & 0x3FF) << 12));
+ else if(nbank == 3)
+ addr = 0x480000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11));
+ else
+ addr = 0x680000 + ((addr & 0x3FF) | ((addr2 & 0x1FF) << 10) | ((nbank - 4) << 19));
+ }
+ else if(nbank == 0)
+ addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10);
+ else if(nbank == 1)
+ {
+ addr &= 0x7FF;
+ addr2 &= 0x3FF;
+ addr = addr + 0x80000 + (addr2 << 11);
+ }
+ else
+ {
+ addr &= 0x7FF;
+ addr2 &= 0x3FF;
+ addr = addr + 0x280000 + ((addr2 << 12) | ((nbank & 1) << 11) | (((nbank - 2) & 6) << 21));
+ }
+ break;
+ case 8192:
+ addr &= 0x7FF;
+ if(nbank < 4)
+ addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13);
+ else
+ addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
+ break;
+ case 9216:
+ if(nbank < 2)
+ addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
+ else if(external_is_RAS)
+ {
+ if(nbank < 6)
+ addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11));
+ else
+ addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21));
+ }
+ else
+ addr = 0x100000 + ((addr & 0xFFF) | ((addr2 & 0x7FF) << 12) | ((nbank - 2) << 23));
+ break;
+ case 10240:
+ if(external_is_RAS)
+ {
+ addr &= 0x7FF;
+ if(nbank < 4)
+ addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13);
+ else
+ addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
+ }
+ else if(nbank == 0)
+ addr = (addr & 0x7FF) | ((addr2 & 0x3FF) << 11);
+ else
+ {
+ addr &= 0xFFF;
+ addr2 &= 0x7FF;
+ addr = addr + 0x200000 + ((addr2 << 12) | ((nbank - 1) << 23));
+ }
+ break;
+ case 11264:
+ if(nbank < 2)
+ addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
+ else if(nbank < 6)
+ addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11));
+ else
+ addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21));
+ break;
+ case 12288:
+ if(external_is_RAS)
+ {
+ addr &= 0x7FF;
+ if(nbank < 4)
+ addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13);
+ else if(nbank < 6)
+ addr |= ((nbank & 1) << 11) | ((addr2 & 0x3FF) << 12) | ((nbank & 4) << 21);
+ else
+ addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
+ }
+ else
+ {
+ if(nbank < 2)
+ addr = (addr & 0x7FF) | (nbank << 11) | ((addr2 & 0x3FF) << 12);
+ else
+ addr = 0x400000 + ((addr & 0xFFF) | ((addr2 & 0x7FF) << 12) | ((nbank - 2) << 23));
+ }
+ break;
+ case 13312:
+ if(nbank < 2)
+ addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11);
+ else if(nbank < 4)
+ addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 12) | ((nbank & 1) << 11));
+ else
+ addr = 0x500000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 13) | ((nbank & 3) << 11));
+ break;
+ case 14336:
+ addr &= 0x7FF;
+ if(nbank < 4)
+ addr |= (nbank << 11) | ((addr2 & 0x3FF) << 13);
+ else if(nbank < 6)
+ addr |= ((nbank & 1) << 11) | ((addr2 & 0x3FF) << 12) | ((nbank & 4) << 21);
+ else
+ addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21);
+ break;
+ case 16384:
+ if(external_is_RAS)
+ {
+ addr &= 0x7FF;
+ addr2 &= 0x3FF;
+ addr |= ((nbank & 3) << 11) | (addr2 << 13) | ((nbank & 4) << 21);
+ }
+ else
+ {
+ addr &= 0xFFF;
+ addr2 &= 0x7FF;
+ if(nbank < 2)
+ addr |= (addr2 << 13) | (nbank << 12);
+ else
+ addr |= (addr2 << 12) | (nbank << 23);
+ }
+ break;
+ default:
+ if(mem_size < 2048 || ((mem_size & 1536) == 512) || (mem_size == 2048 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 6))
+ {
+ addr &= 0x3FF;
+ addr2 &= 0x1FF;
+ addr |= (addr2 << 10) | (nbank << 19);
+ }
+ else if(mem_size < 8192 || (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 0x17)
+ {
+ addr &= 0x7FF;
+ addr2 &= 0x3FF;
+ addr |= (addr2 << 11) | (nbank << 21);
+ }
+ else
+ {
+ addr &= 0xFFF;
+ addr2 &= 0x7FF;
+ addr |= (addr2 << 12) | (nbank << 23);
+ }
+ break;
+ }
}
return addr;
}
-void scat_memmap_state_update()
-{
- int i;
- uint32_t addr;
-
- for(i=16;i<24;i++)
- {
- addr = get_scat_addr(0x40000 + (i << 14), NULL);
- mem_mapping_set_exec(&scat_4000_9FFF_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL);
- }
- addr = get_scat_addr(0xA0000, NULL);
- mem_mapping_set_exec(&scat_A000_BFFF_mapping, addr < (mem_size << 10) ? ram + addr : NULL);
- for(i=0;i<6;i++)
- {
- addr = get_scat_addr(0x100000 + (i << 16), NULL);
- mem_mapping_set_exec(&scat_shadowram_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL);
- }
-
- flushmmucache();
-}
-
void scat_set_global_EMS_state(int state)
{
int i;
@@ -214,21 +892,118 @@ void scat_set_global_EMS_state(int state)
if(state && (scat_stat[i].regs_2x9 & 0x80))
{
virt_addr = get_scat_addr(base_addr, &scat_stat[i]);
- if(i < 24) mem_mapping_disable(&scat_4000_9FFF_mapping[i]);
- mem_mapping_enable(&scat_mapping[i]);
- if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[i], ram + virt_addr);
- else mem_mapping_set_exec(&scat_mapping[i], NULL);
+ if(i < 24) mem_mapping_disable(&scat_4000_EFFF_mapping[i]);
+ else mem_mapping_disable(&scat_4000_EFFF_mapping[i + 12]);
+ mem_mapping_enable(&scat_ems_mapping[i]);
+ if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[i], ram + virt_addr);
+ else mem_mapping_set_exec(&scat_ems_mapping[i], NULL);
}
else
{
- mem_mapping_set_exec(&scat_mapping[i], ram + base_addr);
- mem_mapping_disable(&scat_mapping[i]);
- if(i < 24) mem_mapping_enable(&scat_4000_9FFF_mapping[i]);
+ mem_mapping_set_exec(&scat_ems_mapping[i], ram + base_addr);
+ mem_mapping_disable(&scat_ems_mapping[i]);
+
+ int conf = (scat_regs[SCAT_VERSION] & 0xF0) ? (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) : (scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2);
+ if(i < 24)
+ {
+ if(conf > 1 || (conf == 1 && i < 16))
+ mem_mapping_enable(&scat_4000_EFFF_mapping[i]);
+ else
+ mem_mapping_disable(&scat_4000_EFFF_mapping[i]);
+ }
+ else if(conf > 3 || ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && conf == 2))
+ mem_mapping_enable(&scat_4000_EFFF_mapping[i + 12]);
+ else
+ mem_mapping_disable(&scat_4000_EFFF_mapping[i + 12]);
}
}
flushmmucache();
}
+void scat_memmap_state_update()
+{
+ int i;
+ uint32_t addr;
+
+ for(i=(((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 16);i<44;i++)
+ {
+ addr = get_scat_addr(0x40000 + (i << 14), NULL);
+ mem_mapping_set_exec(&scat_4000_EFFF_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL);
+// pclog("scat_memmap_state_update : Address %06X to %06X\n", 0x40000 + (i << 14), addr);
+ }
+ addr = get_scat_addr(0, NULL);
+// pclog("scat_memmap_state_update : Address 000000 to %06X\n", addr);
+ mem_mapping_set_exec(&scat_low_mapping[0], addr < (mem_size << 10) ? ram + addr : NULL);
+ addr = get_scat_addr(0xF0000, NULL);
+// pclog("scat_memmap_state_update : Address 0F0000 to %06X\n", addr);
+ mem_mapping_set_exec(&scat_low_mapping[1], addr < (mem_size << 10) ? ram + addr : NULL);
+ for(i=2;i<32;i++)
+ {
+ addr = get_scat_addr(i << 19, NULL);
+ mem_mapping_set_exec(&scat_low_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL);
+// pclog("scat_memmap_state_update : Address %06X to %06X\n", i << 19, addr);
+ }
+
+ if((scat_regs[SCAT_VERSION] & 0xF0) == 0)
+ {
+ for(i=0;i < scat_max_map[(scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2)];i++)
+ mem_mapping_enable(&scat_low_mapping[i]);
+ for(;i<32;i++) mem_mapping_disable(&scat_low_mapping[i]);
+
+ for(i=24;i<36;i++)
+ {
+ if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40)) < 4)
+ mem_mapping_disable(&scat_4000_EFFF_mapping[i]);
+ else
+ mem_mapping_enable(&scat_4000_EFFF_mapping[i]);
+ }
+ }
+ else
+ {
+ for(i=0;i < scatsx_max_map[scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F];i++)
+ mem_mapping_enable(&scat_low_mapping[i]);
+ for(;i<32;i++) mem_mapping_disable(&scat_low_mapping[i]);
+
+ for(i=24;i<36;i++)
+ {
+ if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 2 || (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3)
+ mem_mapping_disable(&scat_4000_EFFF_mapping[i]);
+ else
+ mem_mapping_enable(&scat_4000_EFFF_mapping[i]);
+ }
+ }
+
+ if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) || ((scat_regs[SCAT_VERSION] & 0xF0) != 0))
+ {
+ if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3))
+ {
+ mem_mapping_disable(&scat_low_mapping[2]);
+ for(i=0;i<6;i++)
+ {
+ addr = get_scat_addr(0x100000 + (i << 16), NULL);
+ mem_mapping_set_exec(&scat_remap_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL);
+ mem_mapping_enable(&scat_remap_mapping[i]);
+// pclog("scat_memmap_state_update : Address %06X to %06X\n", 0x100000 + (i << 16), addr);
+ }
+ }
+ else
+ {
+ for(i=0;i<6;i++)
+ mem_mapping_disable(&scat_remap_mapping[i]);
+ if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) > 4) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) > 3))
+ mem_mapping_enable(&scat_low_mapping[2]);
+ }
+ }
+ else
+ {
+ for(i=0;i<6;i++)
+ mem_mapping_disable(&scat_remap_mapping[i]);
+ mem_mapping_enable(&scat_low_mapping[2]);
+ }
+
+ scat_set_global_EMS_state(scat_regs[SCAT_EMS_CONTROL] & 0x80);
+}
+
void scat_write(uint16_t port, uint8_t val, void *priv)
{
uint8_t scat_reg_valid = 0, scat_shadow_update = 0, scat_map_update = 0, index;
@@ -271,55 +1046,49 @@ void scat_write(uint16_t port, uint8_t val, void *priv)
scat_reg_valid = 1;
break;
case SCAT_POWER_MANAGEMENT:
- // TODO - Only use AUX parity disable bit for this version. Other bits should be implemented later.
- val &= (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x40 : 0x60;
+ cpu_set_nonturbo_divider((val & 0xc) > 0 ? 1 << ((val & 0xc) >> 2) : 0);
scat_reg_valid = 1;
break;
case SCAT_DRAM_CONFIGURATION:
- if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) || ((scat_regs[SCAT_VERSION] & 0xF0) != 0))
- {
- if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (val & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (val & 0x1F) == 3))
- {
- if(mem_size > 1024) mem_mapping_disable(&ram_high_mapping);
- for(index=0;index<6;index++)
- mem_mapping_enable(&scat_shadowram_mapping[index]);
- }
- else
- {
- for(index=0;index<6;index++)
- mem_mapping_disable(&scat_shadowram_mapping[index]);
- if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping);
- }
- }
- else
- {
- for(index=0;index<6;index++)
- mem_mapping_disable(&scat_shadowram_mapping[index]);
- if(mem_size > 1024) mem_mapping_enable(&ram_high_mapping);
- }
scat_map_update = 1;
+ scat_shadow_update = 1;
if((scat_regs[SCAT_VERSION] & 0xF0) == 0)
{
cpu_waitstates = (val & 0x70) == 0 ? 1 : 2;
cpu_update_waitstates();
}
- else
- {
- if(mem_size != 1024 || ((val & 0x1F) != 2 && (val & 0x1F) != 3))
- val = (val & 0xe0) | scatsx_mem_conf_val[mem_size >> 9];
- }
scat_reg_valid = 1;
break;
case SCAT_EXTENDED_BOUNDARY:
- scat_set_xms_bound(val & ((scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x4f : 0x1f));
+ if((scat_regs[SCAT_VERSION] & 0xF0) == 0)
+ {
+ if(scat_regs[SCAT_VERSION] < 4)
+ {
+ val &= 0xBF;
+ scat_set_xms_bound(val & 0x0f);
+ }
+ else
+ {
+ val = (val & 0x7F) | 0x80;
+ scat_set_xms_bound(val & 0x4f);
+ }
+ }
+ else
+ scat_set_xms_bound(val & 0x1f);
mem_set_mem_state(0x40000, 0x60000, (val & 0x20) ? MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL : MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
- if((val ^ scat_regs[SCAT_EXTENDED_BOUNDARY]) & 0x40) scat_map_update = 1;
+ if((val ^ scat_regs[SCAT_EXTENDED_BOUNDARY]) & 0xC0) scat_map_update = 1;
scat_reg_valid = 1;
break;
case SCAT_ROM_ENABLE:
+ scat_reg_valid = 1;
+ scat_romcs_state_update(val);
+ break;
case SCAT_RAM_WRITE_PROTECT:
+ scat_reg_valid = 1;
+ flushmmucache_cr3();
+ break;
case SCAT_SHADOW_RAM_ENABLE_1:
case SCAT_SHADOW_RAM_ENABLE_2:
case SCAT_SHADOW_RAM_ENABLE_3:
@@ -344,7 +1113,7 @@ void scat_write(uint16_t port, uint8_t val, void *priv)
}
if (scat_reg_valid)
scat_regs[scat_index] = val;
- else pclog("Attemped to write unimplemented SCAT register %02X at %04X:%04X\n", scat_index, val, CS, cpu_state.pc);
+ else pclog("Attemped to write unimplemented SCAT register %02X at %04X:%04X\n", scat_index, val, CS, cpu_state.oldpc);
if (scat_shadow_update)
scat_shadow_state_update();
if (scat_map_update)
@@ -381,8 +1150,8 @@ void scat_write(uint16_t port, uint8_t val, void *priv)
if((scat_regs[SCAT_EMS_CONTROL] & 0x80) && (scat_stat[index].regs_2x9 & 0x80))
{
virt_addr = get_scat_addr(base_addr, &scat_stat[index]);
- if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[index], ram + virt_addr);
- else mem_mapping_set_exec(&scat_mapping[index], NULL);
+ if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[index], ram + virt_addr);
+ else mem_mapping_set_exec(&scat_ems_mapping[index], NULL);
flushmmucache();
}
}
@@ -404,18 +1173,20 @@ void scat_write(uint16_t port, uint8_t val, void *priv)
if (val & 0x80)
{
virt_addr = get_scat_addr(base_addr, &scat_stat[index]);
- if(index < 24) mem_mapping_disable(&scat_4000_9FFF_mapping[index]);
- if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_mapping[index], ram + virt_addr);
- else mem_mapping_set_exec(&scat_mapping[index], NULL);
- mem_mapping_enable(&scat_mapping[index]);
-// pclog("Map page %d(address %05X) to address %06X\n", scat_ems_reg_2xA & 0x1f, base_addr, virt_addr);
+ if(index < 24) mem_mapping_disable(&scat_4000_EFFF_mapping[index]);
+ else mem_mapping_disable(&scat_4000_EFFF_mapping[index + 12]);
+ if(virt_addr < (mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[index], ram + virt_addr);
+ else mem_mapping_set_exec(&scat_ems_mapping[index], NULL);
+ mem_mapping_enable(&scat_ems_mapping[index]);
+// pclog("Map page %d(address %05X) to address %06X\n", index, base_addr, virt_addr);
}
else
{
- mem_mapping_set_exec(&scat_mapping[index], ram + base_addr);
- mem_mapping_disable(&scat_mapping[index]);
- if(index < 24) mem_mapping_enable(&scat_4000_9FFF_mapping[index]);
-// pclog("Unmap page %d(address %06X)\n", scat_ems_reg_2xA & 0x1f, base_addr);
+ mem_mapping_set_exec(&scat_ems_mapping[index], ram + base_addr);
+ mem_mapping_disable(&scat_ems_mapping[index]);
+ if(index < 24) mem_mapping_enable(&scat_4000_EFFF_mapping[index]);
+ else mem_mapping_enable(&scat_4000_EFFF_mapping[index + 12]);
+// pclog("Unmap page %d(address %06X)\n", index, base_addr);
}
flushmmucache();
}
@@ -448,11 +1219,23 @@ uint8_t scat_read(uint16_t port, void *priv)
case SCAT_MISCELLANEOUS_STATUS:
val = (scat_regs[scat_index] & 0x3f) | (~nmi_mask & 0x80) | ((mem_a20_key & 2) << 5);
break;
+ case SCAT_POWER_MANAGEMENT:
+ val = (scat_regs[scat_index] & (cpu_get_turbo() ? 0xF3 : 0xFF));
+ break;
case SCAT_DRAM_CONFIGURATION:
if ((scat_regs[SCAT_VERSION] & 0xF0) == 0) val = (scat_regs[scat_index] & 0x8f) | (cpu_waitstates == 1 ? 0 : 0x10);
- else if(mem_size != 1024) val = (scat_regs[scat_index] & 0xe0) | scatsx_mem_conf_val[mem_size >> 9];
else val = scat_regs[scat_index];
break;
+ case SCAT_EXTENDED_BOUNDARY:
+ val = scat_regs[scat_index];
+ if ((scat_regs[SCAT_VERSION] & 0xF0) == 0)
+ {
+ if((scat_regs[SCAT_VERSION] & 0x0F) >= 4)
+ val |= 0x80;
+ else
+ val &= 0xAF;
+ }
+ break;
default:
val = scat_regs[scat_index];
break;
@@ -496,25 +1279,89 @@ uint8_t scat_read(uint16_t port, void *priv)
return val;
}
-uint8_t mem_read_scatems(uint32_t addr, void *priv)
+uint8_t mem_read_scatb(uint32_t addr, void *priv)
{
uint8_t val = 0xff;
scat_t *stat = (scat_t *)priv;
addr = get_scat_addr(addr, stat);
if (addr < (mem_size << 10))
- val = mem_read_ram(addr, priv);
+ val = ram[addr];
return val;
}
-void mem_write_scatems(uint32_t addr, uint8_t val, void *priv)
+void mem_write_scatb(uint32_t addr, uint8_t val, void *priv)
{
scat_t *stat = (scat_t *)priv;
+ uint32_t oldaddr = addr, chkaddr;
addr = get_scat_addr(addr, stat);
+ chkaddr = stat ? addr : oldaddr;
+ if (chkaddr >= 0xC0000 && chkaddr < 0x100000)
+ {
+ if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return;
+ }
if (addr < (mem_size << 10))
- mem_write_ram(addr, val, priv);
+ ram[addr] = val;
+}
+
+uint16_t mem_read_scatw(uint32_t addr, void *priv)
+{
+ uint16_t val = 0xffff;
+ scat_t *stat = (scat_t *)priv;
+
+ if((addr & 0x3FFF) == 0x3FFF) pclog("mem_read_scatw(%08X, %p) called.\n", addr, priv);
+ addr = get_scat_addr(addr, stat);
+ if (addr < (mem_size << 10))
+ val = *(uint16_t *)&ram[addr];
+
+ return val;
+}
+
+void mem_write_scatw(uint32_t addr, uint16_t val, void *priv)
+{
+ scat_t *stat = (scat_t *)priv;
+ uint32_t oldaddr = addr, chkaddr;
+
+ if((addr & 0x3FFF) == 0x3FFF) pclog("mem_write_scatw(%08X, %04X, %p) called.\n", addr, val, priv);
+ addr = get_scat_addr(addr, stat);
+ chkaddr = stat ? addr : oldaddr;
+ if (chkaddr >= 0xC0000 && chkaddr < 0x100000)
+ {
+ if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return;
+ }
+ if (addr < (mem_size << 10))
+ *(uint16_t *)&ram[addr] = val;
+}
+
+uint32_t mem_read_scatl(uint32_t addr, void *priv)
+{
+ uint32_t val = 0xffffffff;
+ scat_t *stat = (scat_t *)priv;
+
+ if((addr & 0x3FFF) > 0x3FFC) pclog("mem_read_scatl(%08X, %p) called.\n", addr, priv);
+ addr = get_scat_addr(addr, stat);
+ if (addr < (mem_size << 10))
+ val = *(uint32_t *)&ram[addr];
+
+ return val;
+}
+
+void mem_write_scatl(uint32_t addr, uint32_t val, void *priv)
+{
+ scat_t *stat = (scat_t *)priv;
+ uint32_t oldaddr = addr, chkaddr;
+
+ if((addr & 0x3FFF) > 0x3FFC) pclog("mem_write_scatl(%08X, %08X, %p) called.\n", addr, val, priv);
+ addr = get_scat_addr(addr, stat);
+ chkaddr = stat ? addr : oldaddr;
+ if (chkaddr >= 0xC0000 && chkaddr < 0x100000)
+ {
+ if(scat_regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xC0000) >> 15))) return;
+ }
+ if (addr < (mem_size << 10))
+ *(uint32_t *)&ram[addr] = val;
}
void scat_init()
@@ -530,7 +1377,17 @@ void scat_init()
}
scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0;
- scat_regs[SCAT_VERSION] = 4;
+ switch(romset)
+ {
+ case ROM_GW286CT:
+ case ROM_SPC4216P:
+ case ROM_SPC4620P:
+ scat_regs[SCAT_VERSION] = 4;
+ break;
+ default:
+ scat_regs[SCAT_VERSION] = 1;
+ break;
+ }
scat_regs[SCAT_CLOCK_CONTROL] = 2;
scat_regs[SCAT_PERIPHERAL_CONTROL] = 0x80;
scat_regs[SCAT_MISCELLANEOUS_STATUS] = 0x37;
@@ -545,35 +1402,47 @@ void scat_init()
scat_regs[SCAT_EMS_CONTROL] = 0;
scat_port_92 = 0;
- mem_mapping_set_addr(&ram_low_mapping, 0, 0x40000);
-
- for (i = 0; i < 24; i++)
+ mem_mapping_disable(&ram_low_mapping);
+ mem_mapping_disable(&ram_mid_mapping);
+ mem_mapping_disable(&ram_high_mapping);
+ for (i = 0; i < 4; i++)
+ mem_mapping_disable(&bios_mapping[i]);
+ mem_mapping_add(&scat_low_mapping[0], 0, 0x40000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram, MEM_MAPPING_INTERNAL, NULL);
+ mem_mapping_add(&scat_low_mapping[1], 0xF0000, 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + 0xF0000, MEM_MAPPING_INTERNAL, NULL);
+ for(i=2;i<32;i++)
{
- mem_mapping_add(&scat_4000_9FFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL);
- mem_mapping_enable(&scat_4000_9FFF_mapping[i]);
+ mem_mapping_add(&scat_low_mapping[i], (i << 19), 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + (i << 19), MEM_MAPPING_INTERNAL, NULL);
}
+ mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, scat_regs[SCAT_VERSION] < 4 ? 0x40000 : 0x60000);
- mem_mapping_add(&scat_A000_BFFF_mapping, 0xA0000, 0x20000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + 0xA0000, MEM_MAPPING_INTERNAL, NULL);
- mem_mapping_enable(&scat_A000_BFFF_mapping);
+ for (i = 0; i < 44; i++)
+ mem_mapping_add(&scat_4000_EFFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL);
+ for (i = 0; i < 8; i++)
+ {
+ mem_mapping_add(&scat_low_ROMCS_mapping[i], 0xC0000 + (i << 14), 0x4000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL);
+ mem_mapping_disable(&scat_low_ROMCS_mapping[i]);
+ }
for (i = 0; i < 32; i++)
{
scat_stat[i].regs_2x8 = 0xff;
scat_stat[i].regs_2x9 = 0x03;
- mem_mapping_add(&scat_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + ((i + (i >= 24 ? 28 : 16)) << 14), 0, &scat_stat[i]);
- mem_mapping_disable(&scat_mapping[i]);
+ mem_mapping_add(&scat_ems_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + (i >= 24 ? 28 : 16)) << 14), 0, &scat_stat[i]);
}
- // TODO - Only normal CPU accessing address FF0000 to FFFFFF mapped to ROM. Normal CPU accessing address FC0000 to FEFFFF map to ROM should be implemented later.
- for (i = 12; i < 16; i++)
+ for (i = (scat_regs[SCAT_VERSION] < 4 ? 0 : 8); i < 16; i++)
{
mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL);
+ mem_mapping_enable(&scat_high_mapping[i]);
}
for(i=0;i<6;i++)
- mem_mapping_add(&scat_shadowram_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL);
+ mem_mapping_add(&scat_remap_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL);
+
+ external_is_RAS = (scat_regs[SCAT_VERSION] > 3) || (((mem_size & ~2047) >> 11) + ((mem_size & 1536) >> 9) + ((mem_size & 511) >> 7)) > 4;
scat_set_xms_bound(0);
+ scat_memmap_state_update();
scat_shadow_state_update();
}
@@ -610,34 +1479,50 @@ void scatsx_init()
scat_regs[SCATSX_CAS_TIMING_FOR_DMA] = 3;
scat_port_92 = 0;
- mem_mapping_set_addr(&ram_low_mapping, 0, 0x80000);
-
- for (i = 16; i < 24; i++)
+ mem_mapping_disable(&ram_low_mapping);
+ mem_mapping_disable(&ram_mid_mapping);
+ mem_mapping_disable(&ram_high_mapping);
+ for (i = 0; i < 4; i++)
+ mem_mapping_disable(&bios_mapping[i]);
+ mem_mapping_add(&scat_low_mapping[0], 0, 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram, MEM_MAPPING_INTERNAL, NULL);
+ mem_mapping_add(&scat_low_mapping[1], 0xF0000, 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + 0xF0000, MEM_MAPPING_INTERNAL, NULL);
+ for(i=2;i<32;i++)
{
- mem_mapping_add(&scat_4000_9FFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL);
- mem_mapping_enable(&scat_4000_9FFF_mapping[i]);
+ mem_mapping_add(&scat_low_mapping[i], (i << 19), 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + (i << 19), MEM_MAPPING_INTERNAL, NULL);
}
+ mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, 0x40000);
- mem_mapping_add(&scat_A000_BFFF_mapping, 0xA0000, 0x20000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + 0xA0000, MEM_MAPPING_INTERNAL, NULL);
- mem_mapping_enable(&scat_A000_BFFF_mapping);
+ for (i = 16; i < 44; i++)
+ {
+ mem_mapping_add(&scat_4000_EFFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL);
+ mem_mapping_enable(&scat_4000_EFFF_mapping[i]);
+ }
+ for (i = 0; i < 8; i++)
+ {
+ mem_mapping_add(&scat_low_ROMCS_mapping[i], 0xC0000 + (i << 14), 0x4000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL);
+ mem_mapping_disable(&scat_low_ROMCS_mapping[i]);
+ }
for (i = 24; i < 32; i++)
{
scat_stat[i].regs_2x8 = 0xff;
scat_stat[i].regs_2x9 = 0x03;
- mem_mapping_add(&scat_mapping[i], (i + 28) << 14, 0x04000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, ram + ((i + 28) << 14), 0, &scat_stat[i]);
- mem_mapping_disable(&scat_mapping[i]);
+ mem_mapping_add(&scat_ems_mapping[i], (i + 28) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + 28) << 14), 0, &scat_stat[i]);
+ mem_mapping_disable(&scat_ems_mapping[i]);
}
- // TODO - Only normal CPU accessing address FF0000 to FFFFFF mapped to ROM. Normal CPU accessing address FC0000 to FEFFFF map to ROM should be implemented later.
- for (i = 12; i < 16; i++)
+ for (i = 0; i < 16; i++)
{
mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL);
+ mem_mapping_enable(&scat_high_mapping[i]);
}
for(i=0;i<6;i++)
- mem_mapping_add(&scat_shadowram_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatems, NULL, NULL, mem_write_scatems, NULL, NULL, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL);
+ mem_mapping_add(&scat_remap_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL);
+
+ external_is_RAS = scatsx_external_is_RAS[mem_size >> 9];
scat_set_xms_bound(0);
+ scat_memmap_state_update();
scat_shadow_state_update();
}
diff --git a/src/scsi_cd.c b/src/scsi_cd.c
index 48dbdb6..5a56550 100644
--- a/src/scsi_cd.c
+++ b/src/scsi_cd.c
@@ -204,6 +204,8 @@ typedef struct scsi_cd_data_t
int short_seek, long_seek;
int max_speed, cur_speed;
+
+ int cur_model;
} scsi_cd_data_t;
static scsi_cd_data_t *cd_data = NULL;
@@ -266,6 +268,146 @@ void cd_set_speed(int speed)
}
}
+static struct
+{
+ // suffix numbers are sizes from the specs
+ char *vendor_8;
+ char *model_and_firmware_40;
+ char *serial_20;
+ char *model_16;
+ char *firmware_4;
+
+ char *serial2_20;
+ char *firmware2_8;
+ char *model2_40;
+
+ // for PCem config only
+ char *model_string_40;
+ char *model_config_string_40;
+ int interfaces;
+ int speed; // Not an index, but a "speed" value. -1 == allow override
+} const cd_models[] =
+{
+ {
+ // Generic PCem CD
+ "PCem",
+ "PCemCD v1.0",
+ "53R141",
+ "PCemCD",
+ "1.0",
+
+ "",
+ "v1.0",
+ "PCemCD",
+ "PCemCD",
+ "pcemcd",
+ CD_MODEL_INTERFACE_ALL,
+ -1,
+ },
+ {
+ // A 4x CD-ROM drive from Aztech. Choose if your system image has the SGIDECD.SYS driver
+ "AZT",
+ "AZT 46802I v1.15",
+ "53R141", // TODO: clone serial from my real one
+ "46802I",
+ "1.15",
+
+ "",
+ "v1.15",
+ "CDA46802I",
+ "AZT CDA 468-02I 4X",
+ "azt_cda_468_02i_4x",
+ CD_MODEL_INTERFACE_IDE,
+ 4,
+ },
+};
+
+char *cd_model = NULL;
+
+char *cd_get_model(int i)
+{
+ return cd_models[i].model_string_40;
+}
+
+char *cd_get_config_model(int i)
+{
+ return cd_models[i].model_config_string_40;
+}
+
+void cd_set_model(char *model)
+{
+ if (cd_data)
+ {
+ int c = 0;
+
+ while (1)
+ {
+ if (!model)
+ break;
+ if (c > MAX_CD_MODEL)
+ break;
+ if (!strncmp(cd_models[c].model_string_40, model, 40))
+ break;
+
+ c++;
+ }
+
+ cd_data->cur_model = c;
+ }
+}
+
+int cd_get_model_interfaces(int i)
+{
+ return cd_models[i].interfaces;
+}
+
+int cd_get_model_speed(int i)
+{
+ return cd_models[i].speed;
+}
+
+char *cd_model_to_config(char *model)
+{
+ int c = 0;
+
+ while (1)
+ {
+ if (!model)
+ break;
+ if (c > MAX_CD_MODEL)
+ {
+ c = 0; // default
+ break;
+ }
+ if (!strncmp(cd_models[c].model_string_40, model, 40))
+ break;
+
+ c++;
+ }
+ return cd_models[c].model_config_string_40;
+}
+
+char *cd_model_from_config(char *config)
+{
+ int c = 0;
+
+ while (1)
+ {
+ if (!config)
+ break;
+ if (c > MAX_CD_MODEL)
+ {
+ c = 0; // default
+ break;
+ }
+ if (!strncmp(cd_models[c].model_config_string_40, config, 40))
+ break;
+
+ c++;
+ }
+ return cd_models[c].model_string_40;
+}
+
static void scsi_cd_callback(void *p)
{
scsi_cd_data_t *data = p;
@@ -398,6 +540,7 @@ static void *scsi_cd_init(scsi_bus_t *bus, int id)
cd_data = data;
cd_set_speed(cd_speed);
+ cd_set_model(cd_model);
return data;
}
@@ -750,7 +893,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p)
atapi_sense_clear(data, temp_command, 0);
data->bytes_expected = data->data_pos_write = MIN(alloc_length, 18);
- return SCSI_PHASE_DATA_IN;
+ return alloc_length ? SCSI_PHASE_DATA_IN : SCSI_PHASE_STATUS;
case SCSI_SEEK_6:
if (data->cmd_pos == CMD_POS_IDLE)
@@ -800,7 +943,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p)
data->data_pos_read = 0;
data->bytes_expected = data->data_pos_write = MIN(alloc_length, 8);
- return SCSI_PHASE_DATA_IN;
+ return alloc_length ? SCSI_PHASE_DATA_IN : SCSI_PHASE_STATUS;
case GPCMD_READ_TOC_PMA_ATIP:
// pclog("Read TOC ready? %08X\n",ide);
@@ -831,7 +974,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p)
}
data->data_pos_read = 0;
data->bytes_expected = data->data_pos_write = MIN(alloc_length, len);
- return SCSI_PHASE_DATA_IN;
+ return alloc_length ? SCSI_PHASE_DATA_IN : SCSI_PHASE_STATUS;
case GPCMD_READ_CD:
// pclog("Read CD : start LBA %02X%02X%02X%02X Length %02X%02X%02X Flags %02X\n",cdb[2],cdb[3],cdb[4],cdb[5],cdb[6],cdb[7],cdb[8],cdb[9]);
@@ -1032,7 +1175,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p)
data->data_in[1] = data->data_in[2] = data->data_in[3] = 0;
data->bytes_expected = data->data_pos_write = MIN(6, alloc_length);
- return SCSI_PHASE_DATA_IN;
+ return alloc_length ? SCSI_PHASE_DATA_IN : SCSI_PHASE_STATUS;
case GPCMD_MODE_SENSE_6:
case GPCMD_MODE_SENSE_10:
@@ -1070,7 +1213,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p)
data->bytes_expected = data->data_pos_write = MIN(len, alloc_length);
data->cmd_pos = CMD_POS_IDLE;
- return SCSI_PHASE_DATA_IN;
+ return alloc_length ? SCSI_PHASE_DATA_IN : SCSI_PHASE_STATUS;
case GPCMD_MODE_SELECT_6:
case GPCMD_MODE_SELECT_10:
@@ -1176,7 +1319,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p)
data->bytes_expected = data->data_pos_write = MIN(alloc_length, len);
data->cmd_pos = CMD_POS_IDLE;
- return SCSI_PHASE_DATA_IN;
+ return alloc_length ? SCSI_PHASE_DATA_IN : SCSI_PHASE_STATUS;
case GPCMD_READ_DISC_INFORMATION:
alloc_length = cdb[8] | (cdb[7] << 8);
@@ -1192,7 +1335,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p)
data->bytes_expected = data->data_pos_write = MIN(alloc_length, 34);
data->cmd_pos = CMD_POS_IDLE;
- return SCSI_PHASE_DATA_IN;
+ return alloc_length ? SCSI_PHASE_DATA_IN : SCSI_PHASE_STATUS;
case GPCMD_PLAY_AUDIO_10:
case GPCMD_PLAY_AUDIO_12:
@@ -1245,7 +1388,7 @@ static int scsi_cd_command(uint8_t *cdb, void *p)
if (!(cdb[2] & 0x40)) len=4;
data->bytes_expected = data->data_pos_write = MIN(alloc_length, len);
- return SCSI_PHASE_DATA_IN;
+ return alloc_length ? SCSI_PHASE_DATA_IN : SCSI_PHASE_STATUS;
case GPCMD_START_STOP_UNIT:
if (!cdb[4]) atapi->stop();
@@ -1299,11 +1442,11 @@ static int scsi_cd_command(uint8_t *cdb, void *p)
data->data_in[idx++] = 0x01;
data->data_in[idx++] = 0x00;
data->data_in[idx++] = 68;
- ide_padstr8(data->data_in + idx, 8, "PCem"); /* Vendor */
+ ide_padstr8(data->data_in + idx, 8, cd_models[cd_data->cur_model].vendor_8); /* Vendor */
idx += 8;
- ide_padstr8(data->data_in + idx, 40, "PCemCD v1.0"); /* Product */
+ ide_padstr8(data->data_in + idx, 40, cd_models[cd_data->cur_model].model_and_firmware_40); /* Product */
idx += 40;
- ide_padstr8(data->data_in + idx, 20, "53R141"); /* Product */
+ ide_padstr8(data->data_in + idx, 20, cd_models[cd_data->cur_model].serial_20); /* Product */
idx += 20;
break;
@@ -1334,9 +1477,9 @@ static int scsi_cd_command(uint8_t *cdb, void *p)
data->data_in[6] = 0;
data->data_in[7] = 0;
- ide_padstr8(data->data_in + 8, 8, "PCem"); /* Vendor */
- ide_padstr8(data->data_in + 16, 16, "PCemCD"); /* Product */
- ide_padstr8(data->data_in + 32, 4, "1.0"); /* Revision */
+ ide_padstr8(data->data_in + 8, 8, cd_models[cd_data->cur_model].vendor_8); /* Vendor */
+ ide_padstr8(data->data_in + 16, 16, cd_models[cd_data->cur_model].model_16); /* Product */
+ ide_padstr8(data->data_in + 32, 4, cd_models[cd_data->cur_model].firmware_4); /* Revision */
idx = 36;
}
@@ -1345,7 +1488,7 @@ atapi_out:
data->data_in[size_idx] = idx - preamble_len;
data->bytes_expected = data->data_pos_write = MIN(alloc_length, idx);
- return SCSI_PHASE_DATA_IN;
+ return alloc_length ? SCSI_PHASE_DATA_IN : SCSI_PHASE_STATUS;
case GPCMD_PREVENT_REMOVAL:
data->cmd_pos = CMD_POS_IDLE;
@@ -1488,9 +1631,9 @@ static void scsi_cd_atapi_identify(uint16_t *buffer, void *p)
memset(buffer, 0, 512);
buffer[0] = 0x8000 | (5<<8) | 0x80 | (2<<5); /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */
- ide_padstr((char *)(buffer + 10), "", 20); /* Serial Number */
- ide_padstr((char *)(buffer + 23), "v1.0", 8); /* Firmware */
- ide_padstr((char *)(buffer + 27), "PCemCD", 40); /* Model */
+ ide_padstr((char *)(buffer + 10), cd_models[cd_data->cur_model].serial2_20, 20); /* Serial Number */
+ ide_padstr((char *)(buffer + 23), cd_models[cd_data->cur_model].firmware2_8, 8); /* Firmware */
+ ide_padstr((char *)(buffer + 27), cd_models[cd_data->cur_model].model2_40, 40); /* Model */
buffer[49] = 0x300; /*DMA and LBA supported*/
buffer[51] = 120;
buffer[52] = 120;
diff --git a/src/scsi_cd.h b/src/scsi_cd.h
index dc86826..5b3f701 100644
--- a/src/scsi_cd.h
+++ b/src/scsi_cd.h
@@ -5,3 +5,19 @@ int cd_get_speed(int i);
void cd_set_speed(int speed);
extern int cd_speed;
+
+#define MAX_CD_MODEL 1
+
+#define CD_MODEL_INTERFACE_ALL 0 // even when controller is not IDE and not SCSI (to always have the PCemCD model as default, even when not selectable)
+#define CD_MODEL_INTERFACE_IDE 1
+#define CD_MODEL_INTERFACE_SCSI 2
+
+char *cd_get_model(int i);
+char *cd_get_config_model(int i);
+void cd_set_model(char *model);
+int cd_get_model_interfaces(int i);
+int cd_get_model_speed(int i);
+char *cd_model_to_config(char *model);
+char *cd_model_from_config(char *config);
+
+extern char *cd_model;
diff --git a/src/scsi_hd.c b/src/scsi_hd.c
index 914f984..2a064d5 100644
--- a/src/scsi_hd.c
+++ b/src/scsi_hd.c
@@ -414,7 +414,9 @@ static int scsi_hd_command(uint8_t *cdb, void *p)
}
for (; len >= 0; len--)
+ {
add_data_len(0);
+ }
len = data->data_pos_write;
if (cdb[0] == SCSI_MODE_SENSE_6)
diff --git a/src/scsi_ibm.c b/src/scsi_ibm.c
new file mode 100644
index 0000000..708c24e
--- /dev/null
+++ b/src/scsi_ibm.c
@@ -0,0 +1,1278 @@
+#include
+#include
+#include "ibm.h"
+
+#include "device.h"
+#include "dma.h"
+#include "io.h"
+#include "mca.h"
+#include "mem.h"
+#include "pic.h"
+#include "rom.h"
+#include "scsi.h"
+#include "timer.h"
+
+#include "scsi_ibm.h"
+
+#define SCSI_TIME (20)
+#define POLL_TIME (TIMER_USEC * 10)
+#define MAX_BYTES_TRANSFERRED_PER_POLL 50
+
+extern char ide_fn[4][512];
+
+typedef enum
+{
+ SCB_STATE_IDLE,
+ SCB_STATE_START,
+ SCB_STATE_WAIT,
+ SCB_STATE_COMPLETE
+} sbc_state_t;
+
+typedef enum
+{
+ SCSI_STATE_IDLE,
+ SCSI_STATE_SELECT,
+ SCSI_STATE_SELECT_FAILED,
+ SCSI_STATE_SEND_COMMAND,
+ SCSI_STATE_NEXT_PHASE,
+ SCSI_STATE_END_PHASE,
+ SCSI_STATE_READ_DATA,
+ SCSI_STATE_WRITE_DATA,
+ SCSI_STATE_READ_STATUS,
+ SCSI_STATE_READ_MESSAGE
+} scsi_state_t;
+
+typedef struct scb_t
+{
+ uint16_t command;
+ uint16_t enable;
+ uint32_t lba_addr;
+ uint32_t sys_buf_addr;
+ uint32_t sys_buf_byte_count;
+ uint32_t term_status_block_addr;
+ uint32_t scb_chain_addr;
+ uint16_t block_count;
+ uint16_t block_length;
+} scb_t;
+
+typedef struct scsi_ibm_t
+{
+ rom_t bios_rom;
+
+ uint8_t pos_regs[8];
+
+ uint8_t basic_ctrl;
+ uint32_t command;
+
+ uint8_t attention;
+ uint8_t attention_pending;
+ int attention_waiting;
+
+ uint8_t cir[4];
+ uint8_t cir_pending[4];
+
+ uint8_t irq_status;
+
+ uint32_t scb_addr;
+
+ uint8_t status;
+
+ int in_invalid;
+ int in_reset;
+ sbc_state_t scb_state;
+
+ scb_t scb;
+ int scb_id;
+
+ int cmd_status;
+ int cir_status;
+
+ uint8_t pacing;
+
+ uint8_t buf[0x600];
+
+ uint8_t int_buffer[512];
+
+ struct
+ {
+ int phys_id;
+ int lun_id;
+ } dev_id[16];
+
+ struct
+ {
+ int idx, len;
+ uint8_t data[256];
+
+ int data_idx, data_len;
+ uint32_t data_pointer;
+
+ uint8_t last_status;
+
+ int bytes_transferred;
+
+ int target_id;
+ } cdb;
+
+ int irq_requests[16];
+
+ int cmd_timer;
+ pc_timer_t callback_timer;
+
+ scsi_state_t scsi_state;
+ scsi_bus_t bus;
+} scsi_ibm_t;
+
+#define CTRL_RESET (1 << 7)
+#define CTRL_DMA_ENA (1 << 1)
+#define CTRL_IRQ_ENA (1 << 0)
+
+#define STATUS_CMD_FULL (1 << 3)
+#define STATUS_CMD_EMPTY (1 << 2)
+#define STATUS_IRQ (1 << 1)
+#define STATUS_BUSY (1 << 0)
+
+#define ENABLE_PT (1 << 12)
+
+#define CMD_MASK 0xff3f
+#define CMD_ASSIGN 0x040e
+#define CMD_DEVICE_INQUIRY 0x1c0b
+#define CMD_DMA_PACING_CONTROL 0x040d
+#define CMD_FEATURE_CONTROL 0x040c
+#define CMD_GET_POS_INFO 0x1c0a
+#define CMD_INVALID_412 0x0412
+#define CMD_GET_COMPLETE_STATUS 0x1c07
+#define CMD_READ_DATA 0x1c01
+#define CMD_READ_DEVICE_CAPACITY 0x1c09
+#define CMD_REQUEST_SENSE 0x1c08
+#define CMD_RESET 0x0400
+#define CMD_SEND_OTHER_SCSI 0x241f
+#define CMD_UNKNOWN_1c10 0x1c10
+#define CMD_UNKNOWN_1c11 0x1c11
+#define CMD_WRITE_DATA 0x1c02
+#define CMD_VERIFY 0x1c03
+
+#define IRQ_TYPE_NONE 0x0
+#define IRQ_TYPE_SCB_COMPLETE 0x1
+#define IRQ_TYPE_SCB_COMPLETE_RETRY 0x5
+#define IRQ_TYPE_ADAPTER_HW_FAILURE 0x7
+#define IRQ_TYPE_IMM_CMD_COMPLETE 0xa
+#define IRQ_TYPE_COMMAND_FAIL 0xc
+#define IRQ_TYPE_COMMAND_ERROR 0xe
+#define IRQ_TYPE_SW_SEQ_ERROR 0xf
+#define IRQ_TYPE_RESET_COMPLETE 0x10
+
+static void scsi_rethink_irqs(scsi_ibm_t *scsi)
+{
+ int irq_pending = 0;
+ int c;
+
+/* pclog("scsi_rethink_irqs: basic_ctrl=%02x status=%02x\n", scsi->basic_ctrl, scsi->irq_status);
+ pclog(" ");
+ for (c = 0; c < 16; c++)
+ pclog(" %02x", scsi->irq_requests[c]);
+ pclog("\n");*/
+
+ if (!scsi->irq_status)
+ {
+ for (c = 0; c < 16; c++)
+ {
+ if (scsi->irq_requests[c] != IRQ_TYPE_NONE)
+ {
+// pclog(" Found IRQ on %i\n", c);
+ /*Found IRQ*/
+ scsi->irq_status = c | (scsi->irq_requests[c] << 4);
+ scsi->status |= STATUS_IRQ;
+ irq_pending = 1;
+ break;
+ }
+ }
+ }
+ else
+ irq_pending = 1;
+
+ if (scsi->basic_ctrl & CTRL_IRQ_ENA)
+ {
+ if (irq_pending)
+ {
+ picintlevel(1 << 14);
+// pclog(" SCSI assert INT\n");
+ }
+ else
+ {
+ /*No IRQs pending, clear IRQ state*/
+ scsi->irq_status = 0;
+ scsi->status &= ~STATUS_IRQ;
+ picintc(1 << 14);
+// pclog(" SCSI clear INT - no IRQ\n");
+ }
+ }
+ else
+ {
+ picintc(1 << 14);
+// pclog(" SCSI clear INT - IRQs disabled\n");
+ }
+}
+
+static inline void scsi_ibm_set_irq(scsi_ibm_t *scsi, int id, int type)
+{
+// pclog("scsi_ibm_set_irq id=%i type=%x %02x\n", id, type, scsi->irq_status);
+ scsi->irq_requests[id] = type;
+ if (!scsi->irq_status) /*Don't change IRQ status if one is currently being processed*/
+ scsi_rethink_irqs(scsi);
+}
+static inline void scsi_clear_irq(scsi_ibm_t *scsi, int id)
+{
+ scsi->irq_requests[id] = IRQ_TYPE_NONE;
+ scsi_rethink_irqs(scsi);
+}
+
+static uint8_t scsi_read(uint16_t port, void *p)
+{
+ scsi_ibm_t *scsi = (scsi_ibm_t *)p;
+ uint8_t temp = 0xff;
+
+ switch (port & 7)
+ {
+ case 0: case 1: case 2: case 3: /*Command Interface Register*/
+ temp = scsi->cir_pending[port & 3];
+ break;
+
+ case 4: /*Attention Register*/
+ temp = scsi->attention_pending;
+ break;
+ case 5: /*Basic Control Register*/
+ temp = scsi->basic_ctrl;
+ break;
+ case 6: /*IRQ status*/
+ temp = scsi->irq_status;
+ break;
+ case 7: /*Status*/
+ temp = scsi->status;
+ if (scsi->cir_status == 0)
+ temp |= STATUS_CMD_EMPTY;
+ if (scsi->cir_status == 3)
+ temp |= STATUS_CMD_FULL;
+ break;
+ }
+
+// pclog("scsi_read: port=%04x val=%02x %04x(%05x):%04x %i %02x\n", port, temp,CS,cs,cpu_state.pc, 0/*scsi->callback*/, BH);
+ return temp;
+}
+
+static void scsi_write(uint16_t port, uint8_t val, void *p)
+{
+ scsi_ibm_t *scsi = (scsi_ibm_t *)p;
+
+// pclog("scsi_write: port=%04x val=%02x %04x:%04x\n", port, val,CS,cpu_state.pc);
+
+ switch (port & 7)
+ {
+ case 0: case 1: case 2: case 3: /*Command Interface Register*/
+ scsi->cir_pending[port & 3] = val;
+ if (port & 2)
+ scsi->cir_status |= 2;
+ else
+ scsi->cir_status |= 1;
+ break;
+
+ case 4: /*Attention Register*/
+ scsi->attention_pending = val;
+ scsi->attention_waiting = 2;
+ scsi->status |= STATUS_BUSY;
+ break;
+
+ case 5: /*Basic Control Register*/
+ if ((scsi->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET))
+ {
+// pclog("SCSI reset\n");
+ scsi->in_reset = 1;
+ scsi->cmd_timer = SCSI_TIME*2;
+ scsi->status |= STATUS_BUSY;
+ }
+ scsi->basic_ctrl = val;
+ scsi_rethink_irqs(scsi);
+ break;
+
+// default:
+// fatal("scsi_write port=%04x val=%02x\n", port, val);
+ }
+}
+
+static uint16_t scsi_readw(uint16_t port, void *p)
+{
+ scsi_ibm_t *scsi = (scsi_ibm_t *)p;
+ uint16_t temp = 0xffff;
+
+ switch (port & 7)
+ {
+ case 0: /*Command Interface Register*/
+ temp = scsi->cir_pending[0] | (scsi->cir_pending[1] << 8);
+ break;
+ case 2: /*Command Interface Register*/
+ temp = scsi->cir_pending[2] | (scsi->cir_pending[3] << 8);
+ break;
+
+// default:
+// fatal("scsi_readw port=%04x\n", port);
+ }
+
+// pclog("scsi_readw: port=%04x val=%04x\n", port, temp);
+ return temp;
+}
+
+static void scsi_writew(uint16_t port, uint16_t val, void *p)
+{
+ scsi_ibm_t *scsi = (scsi_ibm_t *)p;
+
+ switch (port & 7)
+ {
+ case 0: /*Command Interface Register*/
+ scsi->cir_pending[0] = val & 0xff;
+ scsi->cir_pending[1] = val >> 8;
+ scsi->cir_status |= 1;
+ break;
+ case 2: /*Command Interface Register*/
+ scsi->cir_pending[2] = val & 0xff;
+ scsi->cir_pending[3] = val >> 8;
+ scsi->cir_status |= 2;
+ break;
+
+// default:
+// fatal("scsi_writew port=%04x val=%04x\n", port, val);
+ }
+
+// pclog("scsi_writew: port=%04x val=%04x\n", port, val);
+}
+
+static void sg_fetch_next(scsi_ibm_t *scsi)
+{
+ if (scsi->scb.sys_buf_byte_count > 0)
+ {
+ scsi->cdb.data_idx = 0;
+ scsi->cdb.data_pointer = mem_readl_phys(scsi->scb.sys_buf_addr);
+ scsi->cdb.data_len = mem_readl_phys(scsi->scb.sys_buf_addr + 4);
+// pclog("SG list: from %08x addr=%08x len=%08x\n", scsi->scb.sys_buf_addr, scsi->cdb.data_pointer, scsi->cdb.data_len);
+ scsi->scb.sys_buf_addr += 8;
+ scsi->scb.sys_buf_byte_count -= 8;
+ }
+}
+
+static void process_ibm_cmd(void *p)
+{
+ scsi_ibm_t *scsi = (scsi_ibm_t *)p;
+ scb_t *scb = &scsi->scb;
+ int c;
+ int old_scb_state;
+
+// pclog("scsi_callback: in_reset=%i command=%x\n", scsi->in_reset, scsi->command);
+ if (scsi->in_reset)
+ {
+ scsi->status &= ~STATUS_BUSY;
+
+ scsi->irq_status = 0;
+ for (c = 0; c < 16; c++)
+ scsi_clear_irq(scsi, c);
+ if (scsi->in_reset == 1)
+ {
+ scsi->basic_ctrl |= CTRL_IRQ_ENA;
+ scsi_ibm_set_irq(scsi, 0xf, IRQ_TYPE_RESET_COMPLETE);
+ }
+ else
+ scsi_ibm_set_irq(scsi, 0xf, IRQ_TYPE_RESET_COMPLETE);
+
+ /*Reset device mappings*/
+ for (c = 0; c < 7; c++)
+ {
+ scsi->dev_id[c].phys_id = c;
+ scsi->dev_id[c].lun_id = 0;
+ }
+ for (; c < 15; c++)
+ scsi->dev_id[c].phys_id = -1;
+
+ scsi->in_reset = 0;
+// pclog("scsi reset complete\n");
+ return;
+ }
+ if (scsi->in_invalid)
+ {
+ scsi_ibm_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_ERROR);
+ scsi->in_invalid = 0;
+ return;
+ }
+ do
+ {
+ old_scb_state = scsi->scb_state;
+
+// pclog("scb_state=%i\n", scsi->scb_state);
+ switch (scsi->scb_state)
+ {
+ case SCB_STATE_IDLE:
+ break;
+
+ case SCB_STATE_START:
+ if (scsi->dev_id[scsi->scb_id].phys_id == -1)
+ {
+ scsi_ibm_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL);
+ scsi->scb_state = SCB_STATE_IDLE;
+ mem_writew_phys(scb->term_status_block_addr + 0x7*2, (0xe << 8) | 0);
+ mem_writew_phys(scb->term_status_block_addr + 0x8*2, (0xa << 8) | 0);
+ break;
+ }
+
+ scb->command = mem_readw_phys(scsi->scb_addr);
+ scb->enable = mem_readw_phys(scsi->scb_addr + 0x02);
+ scb->lba_addr = mem_readl_phys(scsi->scb_addr + 0x04);
+ scb->sys_buf_addr = mem_readl_phys(scsi->scb_addr + 0x08);
+ scb->sys_buf_byte_count = mem_readl_phys(scsi->scb_addr + 0x0c);
+ scb->term_status_block_addr = mem_readl_phys(scsi->scb_addr + 0x10);
+ scb->scb_chain_addr = mem_readl_phys(scsi->scb_addr + 0x14);
+ scb->block_count = mem_readw_phys(scsi->scb_addr + 0x18);
+ scb->block_length = mem_readw_phys(scsi->scb_addr + 0x1a);
+
+/* pclog("SCB : \n"
+ " Command = %04x\n"
+ " Enable = %04x\n"
+ " LBA addr = %08x\n"
+ " System buffer addr = %08x\n"
+ " System buffer byte count = %08x\n"
+ " Terminate status block addr = %08x\n"
+ " SCB chain address = %08x\n"
+ " Block count = %04x\n"
+ " Block length = %04x\n",
+ scb->command, scb->enable, scb->lba_addr,
+ scb->sys_buf_addr, scb->sys_buf_byte_count,
+ scb->term_status_block_addr, scb->scb_chain_addr,
+ scb->block_count, scb->block_length);*/
+
+ if (scb->enable & ENABLE_PT)
+ sg_fetch_next(scsi);
+ else
+ {
+ scsi->cdb.data_idx = 0;
+ scsi->cdb.data_pointer = scb->sys_buf_addr;
+ scsi->cdb.data_len = scb->sys_buf_byte_count;
+ }
+
+ switch (scb->command & CMD_MASK)
+ {
+ case CMD_GET_COMPLETE_STATUS:
+ mem_writew_phys(scb->sys_buf_addr + 0x0*2, 0x201); /*SCB status*/
+ mem_writew_phys(scb->sys_buf_addr + 0x1*2, 0); /*Retry counts*/
+ mem_writel_phys(scb->sys_buf_addr + 0x2*2, 0); /*Residual byte count*/
+ mem_writel_phys(scb->sys_buf_addr + 0x4*2, 0); /*Scatter/gather list element address*/
+ mem_writew_phys(scb->sys_buf_addr + 0x6*2, 0xc); /*Device dependent status length*/
+ mem_writew_phys(scb->sys_buf_addr + 0x7*2, scsi->cmd_status << 8);
+ mem_writew_phys(scb->sys_buf_addr + 0x8*2, 0); /*Error*/
+ mem_writew_phys(scb->sys_buf_addr + 0x9*2, 0); /*Reserved*/
+ mem_writew_phys(scb->sys_buf_addr + 0xa*2, 0); /*Cache information status*/
+ mem_writel_phys(scb->sys_buf_addr + 0xb*2, scsi->scb_addr);
+ scsi->scb_state = SCB_STATE_COMPLETE;
+ break;
+
+ case CMD_UNKNOWN_1c10:
+ for (c = 0; c < 0x600 && c < scb->sys_buf_byte_count; c++)
+ scsi->buf[c] = mem_readb_phys(scb->sys_buf_addr + c);
+ scsi->scb_state = SCB_STATE_COMPLETE;
+ break;
+ case CMD_UNKNOWN_1c11:
+ for (c = 0; c < 0x600 && c < scb->sys_buf_byte_count; c++)
+ mem_writeb_phys(scb->sys_buf_addr + c, scsi->buf[c]);
+ scsi->scb_state = SCB_STATE_COMPLETE;
+ break;
+
+ case CMD_GET_POS_INFO:
+ mem_writew_phys(scb->sys_buf_addr + 0x0*2, 0x8eff);
+ mem_writew_phys(scb->sys_buf_addr + 0x1*2, scsi->pos_regs[3] | (scsi->pos_regs[2] << 8));
+ mem_writew_phys(scb->sys_buf_addr + 0x2*2, 0x0e | (scsi->pos_regs[4] << 8));
+ mem_writew_phys(scb->sys_buf_addr + 0x3*2, 1 << 12);
+ mem_writew_phys(scb->sys_buf_addr + 0x4*2, (7 << 8) | 8);
+ mem_writew_phys(scb->sys_buf_addr + 0x5*2, (16 << 8) | scsi->pacing);
+ mem_writew_phys(scb->sys_buf_addr + 0x6*2, (30 << 8) | 1);
+ mem_writew_phys(scb->sys_buf_addr + 0x7*2, 0);
+ mem_writew_phys(scb->sys_buf_addr + 0x8*2, 0);
+ scsi->scb_state = SCB_STATE_COMPLETE;
+ break;
+
+ case CMD_DEVICE_INQUIRY:
+ scsi->cdb.data[0] = SCSI_INQUIRY;
+ scsi->cdb.data[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/
+ scsi->cdb.data[2] = 0; /*Page code*/
+ scsi->cdb.data[3] = 0;
+ scsi->cdb.data[4] = scb->sys_buf_byte_count; /*Allocation length*/
+ scsi->cdb.data[5] = 0; /*Control*/
+ scsi->cdb.idx = 0;
+ scsi->cdb.len = 6;
+ scsi->cdb.target_id = scsi->dev_id[scsi->scb_id].phys_id;
+ scsi->cdb.data_pointer = scb->sys_buf_addr;
+ scsi->cdb.data_idx = 0;
+ scsi->cdb.data_len = scb->sys_buf_byte_count;
+ scsi->scsi_state = SCSI_STATE_SELECT;
+ scsi->scb_state = SCB_STATE_WAIT;
+ return;
+
+ case CMD_SEND_OTHER_SCSI:
+// pclog("SEND_OTHER_SCSI:");
+ for (c = 0; c < 12; c++)
+ {
+ scsi->cdb.data[c] = mem_readb_phys(scsi->scb_addr + 0x18 + c);
+// pclog(" %02x", scsi->cdb.data[c]);
+ }
+// pclog("\n");
+ scsi->cdb.data[1] = (scsi->cdb.data[1] & 0x1f) | (scsi->dev_id[scsi->scb_id].lun_id << 5); /*Patch correct LUN into command*/
+ scsi->cdb.idx = 0;
+ scsi->cdb.len = (scb->lba_addr & 0xff) ? (scb->lba_addr & 0xff) : 6;
+// pclog("SEND_OTHER_SCSI: %04x\n", scb->lba_addr & 0xffff);
+ scsi->cdb.target_id = scsi->dev_id[scsi->scb_id].phys_id;
+ scsi->scsi_state = SCSI_STATE_SELECT;
+ scsi->scb_state = SCB_STATE_WAIT;
+ return;
+
+ case CMD_READ_DEVICE_CAPACITY:
+ scsi->cdb.data[0] = SCSI_READ_CAPACITY_10;
+ scsi->cdb.data[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/
+ scsi->cdb.data[2] = 0; /*LBA*/
+ scsi->cdb.data[3] = 0;
+ scsi->cdb.data[4] = 0;
+ scsi->cdb.data[5] = 0;
+ scsi->cdb.data[6] = 0; /*Reserved*/
+ scsi->cdb.data[7] = 0;
+ scsi->cdb.data[8] = 0;
+ scsi->cdb.data[9] = 0; /*Control*/
+ scsi->cdb.idx = 0;
+ scsi->cdb.len = 10;
+ scsi->cdb.target_id = scsi->dev_id[scsi->scb_id].phys_id;
+ scsi->scsi_state = SCSI_STATE_SELECT;
+ scsi->scb_state = SCB_STATE_WAIT;
+ return;
+
+ case CMD_READ_DATA:
+ scsi->cdb.data[0] = SCSI_READ_10;
+ scsi->cdb.data[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/
+ scsi->cdb.data[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/
+ scsi->cdb.data[3] = (scb->lba_addr >> 16) & 0xff;
+ scsi->cdb.data[4] = (scb->lba_addr >> 8) & 0xff;
+ scsi->cdb.data[5] = scb->lba_addr & 0xff;
+ scsi->cdb.data[6] = 0; /*Reserved*/
+ scsi->cdb.data[7] = (scb->block_count >> 8) & 0xff;
+ scsi->cdb.data[8] = scb->block_count & 0xff;
+ scsi->cdb.data[9] = 0; /*Control*/
+ scsi->cdb.idx = 0;
+ scsi->cdb.len = 10;
+ scsi->cdb.target_id = scsi->dev_id[scsi->scb_id].phys_id;
+ scsi->scsi_state = SCSI_STATE_SELECT;
+ scsi->scb_state = SCB_STATE_WAIT;
+ return;
+
+ case CMD_REQUEST_SENSE:
+ scsi->cdb.data[0] = SCSI_REQUEST_SENSE;
+ scsi->cdb.data[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/
+ scsi->cdb.data[2] = 0;
+ scsi->cdb.data[3] = 0;
+ scsi->cdb.data[4] = scb->block_count & 0xff; /*Allocation length*/
+ scsi->cdb.data[5] = 0;
+ scsi->cdb.idx = 0;
+ scsi->cdb.len = 6;
+ scsi->cdb.target_id = scsi->dev_id[scsi->scb_id].phys_id;
+ scsi->scsi_state = SCSI_STATE_SELECT;
+ scsi->scb_state = SCB_STATE_WAIT;
+ return;
+
+ case CMD_WRITE_DATA:
+ scsi->cdb.data[0] = SCSI_WRITE_10;
+ scsi->cdb.data[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/
+ scsi->cdb.data[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/
+ scsi->cdb.data[3] = (scb->lba_addr >> 16) & 0xff;
+ scsi->cdb.data[4] = (scb->lba_addr >> 8) & 0xff;
+ scsi->cdb.data[5] = scb->lba_addr & 0xff;
+ scsi->cdb.data[6] = 0; /*Reserved*/
+ scsi->cdb.data[7] = (scb->block_count >> 8) & 0xff;
+ scsi->cdb.data[8] = scb->block_count & 0xff;
+ scsi->cdb.data[9] = 0; /*Control*/
+ scsi->cdb.idx = 0;
+ scsi->cdb.len = 10;
+ scsi->cdb.target_id = scsi->dev_id[scsi->scb_id].phys_id;
+ scsi->scsi_state = SCSI_STATE_SELECT;
+ scsi->scb_state = SCB_STATE_WAIT;
+ return;
+
+ case CMD_VERIFY:
+ scsi->cdb.data[0] = SCSI_VERIFY_10;
+ scsi->cdb.data[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/
+ scsi->cdb.data[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/
+ scsi->cdb.data[3] = (scb->lba_addr >> 16) & 0xff;
+ scsi->cdb.data[4] = (scb->lba_addr >> 8) & 0xff;
+ scsi->cdb.data[5] = scb->lba_addr & 0xff;
+ scsi->cdb.data[6] = 0; /*Reserved*/
+ scsi->cdb.data[7] = (scb->block_count >> 8) & 0xff;
+ scsi->cdb.data[8] = scb->block_count & 0xff;
+ scsi->cdb.data[9] = 0; /*Control*/
+ scsi->cdb.idx = 0;
+ scsi->cdb.len = 10;
+ scsi->cdb.target_id = scsi->dev_id[scsi->scb_id].phys_id;
+ scsi->cdb.data_len = 0;
+ scsi->scsi_state = SCSI_STATE_SELECT;
+ scsi->scb_state = SCB_STATE_WAIT;
+ return;
+
+#ifndef RELEASE_BUILD
+ default:
+ fatal("SCB command %04x\n", scb->command);
+#endif
+ }
+ break;
+
+ case SCB_STATE_WAIT:
+ if (scsi->scsi_state == SCSI_STATE_IDLE)
+ {
+ if (scsi->cdb.last_status == STATUS_GOOD)
+ scsi->scb_state = SCB_STATE_COMPLETE;
+ else if (scsi->cdb.last_status == STATUS_CHECK_CONDITION)
+ {
+ scsi_ibm_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL);
+ scsi->scb_state = SCB_STATE_IDLE;
+ mem_writew_phys(scb->term_status_block_addr + 0x7*2, (0xc << 8) | 2);
+ mem_writew_phys(scb->term_status_block_addr + 0x8*2, 0x20);
+ mem_writew_phys(scb->term_status_block_addr + 0xb*2, scsi->scb_addr & 0xffff);
+ mem_writew_phys(scb->term_status_block_addr + 0xc*2, scsi->scb_addr >> 16);
+ }
+#ifndef RELEASE_BUILD
+ else
+ fatal("SCB unknown result %02x\n", scsi->cdb.last_status);
+#endif
+ }
+ else if (scsi->scsi_state == SCSI_STATE_SELECT_FAILED)
+ {
+// pclog("SCB_STATE_WAIT SELECT_FAILED\n");
+ scsi_ibm_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL);
+ scsi->scb_state = SCB_STATE_IDLE;
+ mem_writew_phys(scb->term_status_block_addr + 0x7*2, (0xc << 8) | 2);
+ mem_writew_phys(scb->term_status_block_addr + 0x8*2, 0x10);
+ }
+#ifndef RELEASE_BUILD
+ else
+ fatal("SCB_STATE_WAIT other %i\n", scsi->scsi_state);
+#endif
+ break;
+
+ case SCB_STATE_COMPLETE:
+ if (scb->enable & 1)
+ {
+ scsi->scb_state = SCB_STATE_START;
+ scsi->scb_addr = scb->scb_chain_addr;
+// pclog("Next SCB - %08x\n", scsi->scb_addr);
+ }
+ else
+ {
+ scsi_ibm_set_irq(scsi, scsi->scb_id, IRQ_TYPE_SCB_COMPLETE);
+ scsi->scb_state = SCB_STATE_IDLE;
+ }
+ break;
+ }
+ } while (scsi->scb_state != old_scb_state);
+}
+
+static void process_immediate_command(scsi_ibm_t *scsi)
+{
+ switch (scsi->command & CMD_MASK)
+ {
+ case CMD_ASSIGN:
+// pclog("Assign: adapter dev=%x scsi ID=%i LUN=%i\n", (scsi->command >> 16) & 0xf, (scsi->command >> 20) & 7, (scsi->command >> 24) & 7);
+ if (((scsi->command >> 16) & 0xf) == 0xf && ((scsi->command >> 20) & 7) == 7) /*Device 15 always adapter*/
+ scsi_ibm_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE);
+ else if (((scsi->command >> 16) & 0xf) == 0xf) /*Can not re-assign device 15 (always adapter)*/
+ scsi_ibm_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_FAIL);
+ else if (scsi->command & (1 << 23))
+ {
+ scsi->dev_id[(scsi->command >> 16) & 0xf].phys_id = -1;
+ scsi_ibm_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE);
+ }
+ else if (((scsi->command >> 20) & 7) == 7) /*Can not assign adapter*/
+ scsi_ibm_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_FAIL);
+ else
+ {
+ scsi->dev_id[(scsi->command >> 16) & 0xf].phys_id = (scsi->command >> 20) & 7;
+ scsi->dev_id[(scsi->command >> 16) & 0xf].lun_id = (scsi->command >> 24) & 7;
+ scsi_ibm_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE);
+ }
+ break;
+
+ case CMD_DMA_PACING_CONTROL:
+ scsi->pacing = scsi->cir[2];
+// pclog("Pacing control: %i\n", scsi->pacing);
+ scsi_ibm_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE);
+ break;
+
+ case CMD_FEATURE_CONTROL:
+// pclog("Feature control: timeout=%is d-rate=%i\n", (scsi->command >> 16) & 0x1fff, scsi->command >> 29);
+ scsi_ibm_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE);
+ break;
+
+ case CMD_INVALID_412:
+ scsi_ibm_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE);
+ break;
+
+ case CMD_RESET:
+ if ((scsi->attention & 0xf) == 0xf) /*Adapter reset*/
+ {
+ scsi_bus_reset(&scsi->bus);
+ scsi->scb_state = SCB_STATE_IDLE;
+ }
+ else /*Device reset*/
+ {
+ }
+ scsi_ibm_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE);
+ break;
+
+ default:
+ fatal("scsi_callback: Bad command %02x\n", scsi->command);
+ }
+}
+
+static int wait_for_bus(scsi_bus_t *bus, int state, int req_needed)
+{
+ int c;
+
+ for (c = 0; c < 20; c++)
+ {
+ int bus_state = scsi_bus_read(bus);
+
+ if ((bus_state & (BUS_IO | BUS_CD | BUS_MSG)) == state && (bus_state & BUS_BSY))
+ {
+ if (!req_needed || (bus_state & BUS_REQ))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void process_scsi(scsi_ibm_t *scsi)
+{
+ int c;
+ int bytes_transferred = 0;
+
+ switch (scsi->scsi_state)
+ {
+ case SCSI_STATE_IDLE:
+ break;
+
+ case SCSI_STATE_SELECT:
+ scsi->cdb.last_status = 0;
+// pclog("Select target ID %i\n", scsi->cdb.target_id);
+ scsi_bus_update(&scsi->bus, BUS_SEL | BUS_SETDATA(1 << scsi->cdb.target_id));
+ if (!(scsi_bus_read(&scsi->bus) & BUS_BSY) || scsi->cdb.target_id > 6)
+ {
+// pclog("STATE_SCSI_SELECT failed to select target %i\n", scsi->cdb.target_id);
+ scsi->scsi_state = SCSI_STATE_SELECT_FAILED;
+ if (!scsi->cmd_timer)
+ scsi->cmd_timer = 1;
+ break;
+ }
+
+ scsi_bus_update(&scsi->bus, 0);
+ if (!(scsi_bus_read(&scsi->bus) & BUS_BSY))
+ {
+// pclog("STATE_SCSI_SELECT failed to select target %i 2\n", scsi->cdb.target_id);
+ scsi->scsi_state = SCSI_STATE_SELECT_FAILED;
+ if (!scsi->cmd_timer)
+ scsi->cmd_timer = 1;
+ break;
+ }
+
+ /*Device should now be selected*/
+ if (!wait_for_bus(&scsi->bus, BUS_CD, 1))
+ {
+// pclog("Device failed to request command\n");
+ scsi->scsi_state = SCSI_STATE_SELECT_FAILED;
+ if (!scsi->cmd_timer)
+ scsi->cmd_timer = 1;
+ break;
+ }
+
+ scsi->scsi_state = SCSI_STATE_SEND_COMMAND;
+ break;
+
+ case SCSI_STATE_SELECT_FAILED:
+ break;
+
+ case SCSI_STATE_SEND_COMMAND:
+ while (scsi->cdb.idx < scsi->cdb.len && bytes_transferred < MAX_BYTES_TRANSFERRED_PER_POLL)
+ {
+ int bus_out;
+
+ for (c = 0; c < 20; c++)
+ {
+ int bus_state = scsi_bus_read(&scsi->bus);
+
+#ifndef RELEASE_BUILD
+ if (!(bus_state & BUS_BSY))
+ fatal("SEND_COMMAND - dropped BSY\n");
+ if ((bus_state & (BUS_IO | BUS_CD | BUS_MSG)) != BUS_CD)
+ fatal("SEND_COMMAND - bus phase incorrect\n");
+#endif
+ if (bus_state & BUS_REQ)
+ break;
+ }
+ if (c == 20)
+ {
+// pclog("SEND_COMMAND timed out\n");
+ break;
+ }
+
+ bus_out = BUS_SETDATA(scsi->cdb.data[scsi->cdb.idx]);
+// pclog(" Command send %02x %i\n", scsi->cdb.data[scsi->cdb.idx], scsi->cdb.len);
+ scsi->cdb.idx++;
+ bytes_transferred++;
+
+ scsi_bus_update(&scsi->bus, bus_out | BUS_ACK);
+ scsi_bus_update(&scsi->bus, bus_out & ~BUS_ACK);
+ }
+ if (scsi->cdb.idx == scsi->cdb.len)
+ scsi->scsi_state = SCSI_STATE_NEXT_PHASE;
+ break;
+
+ case SCSI_STATE_NEXT_PHASE:
+ /*Wait for SCSI command to move to next phase*/
+ for (c = 0; c < 20; c++)
+ {
+ int bus_state = scsi_bus_read(&scsi->bus);
+#ifndef RELEASE_BUILD
+ if (!(bus_state & BUS_BSY))
+ fatal("NEXT_PHASE - dropped BSY waiting\n");
+#endif
+ if (bus_state & BUS_REQ)
+ {
+ int bus_out;
+// pclog("SCSI next phase - %x\n", bus_state);
+ switch (bus_state & (BUS_IO | BUS_CD | BUS_MSG))
+ {
+ case 0:
+// pclog("Move to write data\n");
+ scsi->scsi_state = SCSI_STATE_WRITE_DATA;
+ break;
+
+ case BUS_IO:
+// pclog("Move to read data\n");
+ scsi->scsi_state = SCSI_STATE_READ_DATA;
+ break;
+
+ case (BUS_CD | BUS_IO):
+// pclog("Move to read status\n");
+ scsi->scsi_state = SCSI_STATE_READ_STATUS;
+ break;
+
+ case (BUS_CD | BUS_IO | BUS_MSG):
+// pclog("Move to read message\n");
+ scsi->scsi_state = SCSI_STATE_READ_MESSAGE;
+ break;
+
+ case BUS_CD:
+ bus_out = BUS_SETDATA(0);
+
+ scsi_bus_update(&scsi->bus, bus_out | BUS_ACK);
+ scsi_bus_update(&scsi->bus, bus_out & ~BUS_ACK);
+ break;
+
+#ifndef RELEASE_BUILD
+ default:
+ fatal(" Bad new phase %x\n", bus_state);
+#endif
+ }
+ break;
+ }
+ }
+ break;
+
+ case SCSI_STATE_END_PHASE:
+ /*Wait for SCSI command to move to next phase*/
+ for (c = 0; c < 20; c++)
+ {
+ int bus_state = scsi_bus_read(&scsi->bus);
+
+ if (!(bus_state & BUS_BSY))
+ {
+// pclog("END_PHASE - dropped BSY waiting\n");
+// if (scsi->ccb.req_sense_len == CCB_SENSE_NONE)
+// fatal("No sense data\n");
+ scsi->scsi_state = SCSI_STATE_IDLE;
+// pclog("End of command\n");
+ if (!scsi->cmd_timer)
+ scsi->cmd_timer = 1;
+ break;
+ }
+#ifndef RELEASE_BUILD
+ if (bus_state & BUS_REQ)
+ fatal("END_PHASE - unexpected REQ\n");
+#endif
+ }
+ break;
+
+ case SCSI_STATE_READ_DATA:
+ while (scsi->scsi_state == SCSI_STATE_READ_DATA && bytes_transferred < MAX_BYTES_TRANSFERRED_PER_POLL)
+ {
+ int d;
+
+ for (d = 0; d < 20; d++)
+ {
+ int bus_state = scsi_bus_read(&scsi->bus);
+#ifndef RELEASE_BUILD
+ if (!(bus_state & BUS_BSY))
+ fatal("READ_DATA - dropped BSY waiting\n");
+#endif
+ if ((bus_state & (BUS_IO | BUS_CD | BUS_MSG)) != BUS_IO)
+ {
+// pclog("READ_DATA - changed phase\n");
+ scsi->scsi_state = SCSI_STATE_NEXT_PHASE;
+ break;
+ }
+
+ if (bus_state & BUS_REQ)
+ {
+ uint8_t data = BUS_GETDATA(bus_state);
+ int bus_out = 0;
+
+ if (scsi->cdb.data_idx < scsi->cdb.data_len)
+ {
+ if (scsi->cdb.data_pointer == -1)
+ scsi->int_buffer[scsi->cdb.data_idx] = data;
+ else
+ mem_writeb_phys(scsi->cdb.data_pointer + scsi->cdb.data_idx, data);
+ scsi->cdb.data_idx++;
+
+ if ((scsi->scb.enable & ENABLE_PT) && scsi->cdb.data_idx == scsi->cdb.data_len)
+ sg_fetch_next(scsi);
+ }
+ scsi->cdb.bytes_transferred++;
+
+// pclog("Read data %02x %i %06x\n", data, scsi->cdb.data_idx, scsi->cdb.data_pointer + scsi->cdb.data_idx);
+ scsi_bus_update(&scsi->bus, bus_out | BUS_ACK);
+ scsi_bus_update(&scsi->bus, bus_out & ~BUS_ACK);
+ break;
+ }
+ }
+
+ bytes_transferred++;
+ }
+ break;
+
+ case SCSI_STATE_WRITE_DATA:
+ while (scsi->scsi_state == SCSI_STATE_WRITE_DATA && bytes_transferred < MAX_BYTES_TRANSFERRED_PER_POLL)
+ {
+ int d;
+
+ for (d = 0; d < 20; d++)
+ {
+ int bus_state = scsi_bus_read(&scsi->bus);
+#ifndef RELEASE_BUILD
+ if (!(bus_state & BUS_BSY))
+ fatal("WRITE_DATA - dropped BSY waiting\n");
+#endif
+ if ((bus_state & (BUS_IO | BUS_CD | BUS_MSG)) != 0)
+ {
+// pclog("WRITE_DATA - changed phase\n");
+ scsi->scsi_state = SCSI_STATE_NEXT_PHASE;
+ break;
+ }
+
+ if (bus_state & BUS_REQ)
+ {
+ uint8_t data;// = BUS_GETDATA(bus_state);
+ int bus_out;
+
+ if (scsi->cdb.data_idx < scsi->cdb.data_len)
+ {
+ if (scsi->cdb.data_pointer == -1)
+ data = scsi->int_buffer[scsi->cdb.data_idx];
+ else
+ data = mem_readb_phys(scsi->cdb.data_pointer + scsi->cdb.data_idx);
+
+ scsi->cdb.data_idx++;
+ if ((scsi->scb.enable & ENABLE_PT) && scsi->cdb.data_idx == scsi->cdb.data_len)
+ sg_fetch_next(scsi);
+ }
+ else
+ data = 0xff;
+ scsi->cdb.bytes_transferred++;
+
+// pclog("Write data %02x %i\n", data, scsi->cdb.data_idx);
+ bus_out = BUS_SETDATA(data);
+ scsi_bus_update(&scsi->bus, bus_out | BUS_ACK);
+ scsi_bus_update(&scsi->bus, bus_out & ~BUS_ACK);
+ break;
+ }
+ }
+
+ bytes_transferred++;
+ }
+// if (scsi->cdb.data_idx == scsi->cdb.data_len)
+// scsi->scsi_state = SCSI_STATE_NEXT_PHASE;
+ break;
+
+ case SCSI_STATE_READ_STATUS:
+ for (c = 0; c < 20; c++)
+ {
+ int bus_state = scsi_bus_read(&scsi->bus);
+#ifndef RELEASE_BUILD
+ if (!(bus_state & BUS_BSY))
+ fatal("READ_STATUS - dropped BSY waiting\n");
+#endif
+ if ((bus_state & (BUS_IO | BUS_CD | BUS_MSG)) != (BUS_CD | BUS_IO))
+ {
+// pclog("READ_STATUS - changed phase\n");
+ scsi->scsi_state = SCSI_STATE_NEXT_PHASE;
+ break;
+ }
+
+ if (bus_state & BUS_REQ)
+ {
+ uint8_t status = BUS_GETDATA(bus_state);
+ int bus_out = 0;
+
+// pclog("Read status %02x\n", status);
+ scsi->cdb.last_status = status;
+
+ scsi_bus_update(&scsi->bus, bus_out | BUS_ACK);
+ scsi_bus_update(&scsi->bus, bus_out & ~BUS_ACK);
+
+ scsi->scsi_state = SCSI_STATE_NEXT_PHASE;
+ break;
+ }
+ }
+ break;
+
+ case SCSI_STATE_READ_MESSAGE:
+ for (c = 0; c < 20; c++)
+ {
+ int bus_state = scsi_bus_read(&scsi->bus);
+#ifndef RELEASE_BUILD
+ if (!(bus_state & BUS_BSY))
+ fatal("READ_MESSAGE - dropped BSY waiting\n");
+#endif
+ if ((bus_state & (BUS_IO | BUS_CD | BUS_MSG)) != (BUS_CD | BUS_IO | BUS_MSG))
+ {
+// pclog("READ_MESSAGE - changed phase\n");
+ scsi->scsi_state = SCSI_STATE_NEXT_PHASE;
+ break;
+ }
+
+ if (bus_state & BUS_REQ)
+ {
+ uint8_t msg = BUS_GETDATA(bus_state);
+ int bus_out = 0;
+
+// pclog("Read message %02x\n", msg);
+ scsi_bus_update(&scsi->bus, bus_out | BUS_ACK);
+ scsi_bus_update(&scsi->bus, bus_out & ~BUS_ACK);
+
+ switch (msg)
+ {
+ case MSG_COMMAND_COMPLETE:
+ scsi->scsi_state = SCSI_STATE_END_PHASE;
+ break;
+#ifndef RELEASE_BUILD
+ default:
+ fatal("READ_MESSAGE - unknown message %02x\n", msg);
+#endif
+ }
+ break;
+ }
+ }
+ break;
+
+#ifndef RELEASE_BUILD
+ default:
+ fatal("Unknown SCSI_state %d\n", scsi->scsi_state);
+#endif
+ }
+}
+
+static void scsi_callback(void *p)
+{
+ scsi_ibm_t *scsi = (scsi_ibm_t *)p;
+
+ timer_advance_u64(&scsi->callback_timer, POLL_TIME);
+
+// pclog("poll %i\n", scsi->cmd_state);
+ if (scsi->cmd_timer)
+ {
+ scsi->cmd_timer--;
+ if (!scsi->cmd_timer)
+ process_ibm_cmd(scsi);
+ }
+ if (scsi->attention_waiting &&
+ (scsi->scb_state == SCB_STATE_IDLE || (scsi->attention_pending & 0xf0) == 0xe0))
+ {
+ scsi->attention_waiting--;
+ if (!scsi->attention_waiting)
+ {
+// pclog("Process attention request\n");
+ scsi->attention = scsi->attention_pending;
+ scsi->status &= ~STATUS_BUSY;
+ scsi->cir[0] = scsi->cir_pending[0];
+ scsi->cir[1] = scsi->cir_pending[1];
+ scsi->cir[2] = scsi->cir_pending[2];
+ scsi->cir[3] = scsi->cir_pending[3];
+ scsi->cir_status = 0;
+
+ switch (scsi->attention >> 4)
+ {
+ case 0x1: /*Immediate command*/
+ scsi->cmd_status = 0xa;
+ scsi->command = scsi->cir[0] | (scsi->cir[1] << 8) | (scsi->cir[2] << 16) | (scsi->cir[3] << 24);
+ switch (scsi->command & CMD_MASK)
+ {
+ case CMD_ASSIGN:
+ case CMD_DMA_PACING_CONTROL:
+ case CMD_FEATURE_CONTROL:
+ case CMD_INVALID_412:
+ case CMD_RESET:
+ process_immediate_command(scsi);
+ break;
+
+#ifndef RELEASE_BUILD
+ default:
+ fatal("Unknown immediate command %08x\n", scsi->command);
+#endif
+ }
+ break;
+
+ case 0x3: case 0x4: case 0xf: /*Start SCB*/
+ scsi->cmd_status = 0x1;
+ scsi->scb_addr = scsi->cir[0] | (scsi->cir[1] << 8) | (scsi->cir[2] << 16) | (scsi->cir[3] << 24);
+ scsi->scb_state = SCB_STATE_START;
+ scsi->scb_id = scsi->attention & 0xf;
+ scsi->cmd_timer = SCSI_TIME*2;
+// pclog("Start SCB at %08x\n", scsi->scb_addr);
+ break;
+
+ case 5: /*Invalid*/
+ case 0xa: /*Invalid*/
+ scsi->in_invalid = 1;
+ scsi->cmd_timer = SCSI_TIME*2;
+ break;
+
+ case 0xe: /*EOI*/
+ scsi->irq_status = 0;
+ scsi_clear_irq(scsi, scsi->attention & 0xf);
+ break;
+#ifndef RELEASE_BUILD
+ default:
+ fatal("Attention Register 5 %02x\n", scsi->attention);
+#endif
+ }
+ }
+ }
+ process_scsi(scsi);
+}
+
+static uint8_t scsi_ibm_mca_read(int port, void *p)
+{
+ scsi_ibm_t *scsi = (scsi_ibm_t *)p;
+
+// pclog("scsi_mca_read: port=%04x %02x %04x:%04x\n", port, scsi->pos_regs[port & 7], CS,cpu_state.pc);
+
+ return scsi->pos_regs[port & 7];
+}
+
+static void scsi_ibm_mca_write(int port, uint8_t val, void *p)
+{
+ scsi_ibm_t *scsi = (scsi_ibm_t *)p;
+
+ if (port < 0x102)
+ return;
+
+// pclog("scsi_mca_write: port=%04x val=%02x %04x:%04x\n", port, val, CS, cpu_state.pc);
+
+ io_removehandler((((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540, 0x0008, scsi_read, scsi_readw, NULL, scsi_write, scsi_writew, NULL, scsi);
+ mem_mapping_disable(&scsi->bios_rom.mapping);
+
+ scsi->pos_regs[port & 7] = val;
+
+ if (scsi->pos_regs[2] & 1)
+ {
+// pclog(" scsi io = %04x\n", (((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540);
+ io_sethandler((((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540, 0x0008, scsi_read, scsi_readw, NULL, scsi_write, scsi_writew, NULL, scsi);
+ if ((scsi->pos_regs[2] & 0xf0) != 0xf0)
+ {
+ mem_mapping_enable(&scsi->bios_rom.mapping);
+ mem_mapping_set_addr(&scsi->bios_rom.mapping, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000, 0x8000);
+// pclog("SCSI BIOS ROM at %05x %02x\n", ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000, scsi->pos_regs[2]);
+ }
+ }
+}
+
+static void scsi_ibm_reset(void *p)
+{
+ scsi_ibm_t *scsi = (scsi_ibm_t *)p;
+
+// pclog("scsi_ibm_reset\n");
+ scsi->in_reset = 2;
+ scsi->cmd_timer = SCSI_TIME * 50;
+ scsi->status = STATUS_BUSY;
+ scsi->scsi_state = SCSI_STATE_IDLE;
+ scsi->scb_state = SCB_STATE_IDLE;
+ scsi->in_invalid = 0;
+ scsi->attention_waiting = 0;
+ scsi->basic_ctrl = 0;
+ scsi_bus_reset(&scsi->bus);
+}
+
+static void *scsi_ibm_init()
+{
+ int c;
+ scsi_ibm_t *scsi = malloc(sizeof(scsi_ibm_t));
+ memset(scsi, 0, sizeof(scsi_ibm_t));
+
+ rom_init_interleaved(&scsi->bios_rom, "92F2244.U68", "92F2245.U69", 0xc8000, 0x8000, 0x7fff, 0x4000, MEM_MAPPING_EXTERNAL);
+ mem_mapping_disable(&scsi->bios_rom.mapping);
+
+ timer_add(&scsi->callback_timer, scsi_callback, scsi, 1);
+
+ mca_add(scsi_ibm_mca_read, scsi_ibm_mca_write, scsi_ibm_reset, scsi);
+
+ scsi->pos_regs[0] = 0xff;
+ scsi->pos_regs[1] = 0x8e;
+
+ scsi->in_reset = 2;
+ scsi->cmd_timer = SCSI_TIME * 50;
+ scsi->status = STATUS_BUSY;
+
+ scsi_bus_init(&scsi->bus);
+
+/* for (c = 0; c < 7; c++)
+ {
+ scsi->dev_id[c].phys_id = c;
+ scsi->dev_id[c].lun_id = 0;
+ }*/
+ for (c = 0; c < 15; c++)
+ scsi->dev_id[c].phys_id = -1;
+ scsi->dev_id[15].phys_id = 7;
+
+ return scsi;
+}
+
+static void scsi_ibm_close(void *p)
+{
+ scsi_ibm_t *scsi = (scsi_ibm_t *)p;
+
+ free(scsi);
+}
+
+static int scsi_ibm_available()
+{
+ return rom_present("92F2244.U68") && rom_present("92F2245.U69");
+}
+
+device_t scsi_ibm_device =
+{
+ "IBM SCSI Adapter with Cache (MCA)",
+ DEVICE_MCA,
+ scsi_ibm_init,
+ scsi_ibm_close,
+ scsi_ibm_available,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
diff --git a/src/scsi_ibm.h b/src/scsi_ibm.h
new file mode 100644
index 0000000..b528486
--- /dev/null
+++ b/src/scsi_ibm.h
@@ -0,0 +1 @@
+extern device_t scsi_ibm_device;
diff --git a/src/serial.c b/src/serial.c
index 2866f7c..91cf7e8 100644
--- a/src/serial.c
+++ b/src/serial.c
@@ -111,7 +111,8 @@ void serial_write(uint16_t addr, uint8_t val, void *p)
serial_update_ints(serial);
break;
case 2:
- serial->fcr = val;
+ if (serial->has_fifo)
+ serial->fcr = val;
break;
case 3:
serial->lcr = val;
@@ -247,7 +248,7 @@ void serial_receive_callback(void *p)
}
/*Tandy might need COM1 at 2f8*/
-void serial1_init(uint16_t addr, int irq)
+void serial1_init(uint16_t addr, int irq, int has_fifo)
{
memset(&serial1, 0, sizeof(serial1));
io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1);
@@ -255,6 +256,7 @@ void serial1_init(uint16_t addr, int irq)
serial1.addr = addr;
serial1.rcr_callback = NULL;
timer_add(&serial1.receive_timer, serial_receive_callback, &serial1, 0);
+ serial1.has_fifo = has_fifo;
}
void serial1_set(uint16_t addr, int irq)
{
@@ -263,12 +265,16 @@ void serial1_set(uint16_t addr, int irq)
serial1.irq = irq;
serial1.addr = addr;
}
+void serial1_set_has_fifo(int has_fifo)
+{
+ serial1.has_fifo = has_fifo;
+}
void serial1_remove()
{
io_removehandler(serial1.addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1);
}
-void serial2_init(uint16_t addr, int irq)
+void serial2_init(uint16_t addr, int irq, int has_fifo)
{
memset(&serial2, 0, sizeof(serial2));
io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2);
@@ -276,6 +282,7 @@ void serial2_init(uint16_t addr, int irq)
serial2.addr = addr;
serial2.rcr_callback = NULL;
timer_add(&serial2.receive_timer, serial_receive_callback, &serial2, 0);
+ serial2.has_fifo = has_fifo;
}
void serial2_set(uint16_t addr, int irq)
{
@@ -284,6 +291,10 @@ void serial2_set(uint16_t addr, int irq)
serial2.irq = irq;
serial2.addr = addr;
}
+void serial2_set_has_fifo(int has_fifo)
+{
+ serial2.has_fifo = has_fifo;
+}
void serial2_remove()
{
io_removehandler(serial2.addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2);
diff --git a/src/serial.h b/src/serial.h
index 453acbf..13cee6d 100644
--- a/src/serial.h
+++ b/src/serial.h
@@ -1,9 +1,11 @@
#include "timer.h"
-void serial1_init(uint16_t addr, int irq);
-void serial2_init(uint16_t addr, int irq);
+void serial1_init(uint16_t addr, int irq, int has_fifo);
+void serial2_init(uint16_t addr, int irq, int has_fifo);
void serial1_set(uint16_t addr, int irq);
void serial2_set(uint16_t addr, int irq);
+void serial1_set_has_fifo(int has_fifo);
+void serial2_set_has_fifo(int has_fifo);
void serial1_remove();
void serial2_remove();
void serial_reset();
@@ -26,6 +28,7 @@ typedef struct
void *rcr_callback_p;
uint8_t fifo[256];
int fifo_read, fifo_write;
+ int has_fifo;
pc_timer_t receive_timer;
} SERIAL;
diff --git a/src/sio.c b/src/sio.c
index bc2dc33..65c8980 100644
--- a/src/sio.c
+++ b/src/sio.c
@@ -8,9 +8,23 @@
#include "sio.h"
+typedef struct sio_t
+{
+ struct
+ {
+ uint8_t apmc, apms;
+ } pm;
+} sio_t;
+static sio_t sio;
static uint8_t card_sio[256];
//static int pci_cards_ids[4];
+#define REG_SMIEN 0xa2
+#define REG_SMIREQ 0xaa
+
+#define SMIEN_APMC (1 << 7)
+#define SMIREQ_RAPMC (1 << 7)
+
void sio_write(int func, int addr, uint8_t val, void *priv)
{
// pclog("sio_write: func=%d addr=%02x val=%02x %04x:%08x\n", func, addr, val, CS, cpu_state.pc);
@@ -70,6 +84,13 @@ void sio_write(int func, int addr, uint8_t val, void *priv)
else
pci_set_irq_routing(PCI_INTD, val & 0xf);
break;
+
+ case REG_SMIREQ:
+ card_sio[addr] &= val;
+ return;
+ case REG_SMIREQ+1:
+ card_sio[addr] &= val;
+ return;
}
card_sio[addr] = val;
}
@@ -83,8 +104,53 @@ uint8_t sio_read(int func, int addr, void *priv)
return card_sio[addr];
}
+static uint8_t sio_apm_read(uint16_t port, void *p)
+{
+ sio_t *sio = (sio_t *)p;
+ uint8_t ret = 0xff;
+
+ switch (port)
+ {
+ case 0xb2:
+ ret = sio->pm.apmc;
+ break;
+
+ case 0xb3:
+ ret = sio->pm.apms;
+ break;
+ }
+// pclog("sio_apm_read: port=%04x ret=%02x\n", port, ret);
+ return ret;
+}
+
+static void sio_apm_write(uint16_t port, uint8_t val, void *p)
+{
+ sio_t *sio = (sio_t *)p;
+
+// pclog("sio_apm_write: port=%04x val=%02x\n", port, val);
+
+ switch (port)
+ {
+ case 0xb2:
+ sio->pm.apmc = val;
+ if (card_sio[REG_SMIEN] & SMIEN_APMC)
+ {
+ card_sio[REG_SMIREQ] |= SMIREQ_RAPMC;
+// pclog("APMC write causes SMI\n");
+ x86_smi_trigger();
+ }
+ break;
+
+ case 0xb3:
+ sio->pm.apms = val;
+ break;
+ }
+}
+
void sio_init(int card, int pci_a, int pci_b, int pci_c, int pci_d)
{
+ memset(&sio, 0, sizeof(sio_t));
+
pci_add_specific(card, sio_read, sio_write, NULL);
memset(card_sio, 0, 256);
@@ -116,4 +182,6 @@ void sio_init(int card, int pci_a, int pci_b, int pci_c, int pci_d)
pci_set_card_routing(pci_c, PCI_INTC);
if (pci_d)
pci_set_card_routing(pci_d, PCI_INTD);
+
+ io_sethandler(0x00b2, 0x0002, sio_apm_read, NULL, NULL, sio_apm_write, NULL, NULL, &sio);
}
diff --git a/src/slirp/slirp.h b/src/slirp/slirp.h
index 416b402..6e15943 100644
--- a/src/slirp/slirp.h
+++ b/src/slirp/slirp.h
@@ -80,6 +80,10 @@ typedef char *SLIRPcaddr_t;
# include
#endif
+#ifdef HAVE_UNISTD_H
+# include
+#endif
+
#ifndef _MSC_VER
#include
#else
diff --git a/src/sound.c b/src/sound.c
index a5e7320..f038613 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -15,6 +15,7 @@
#include "sound_adlib.h"
#include "sound_adlibgold.h"
#include "sound_audiopci.h"
+#include "sound_azt2316a.h"
#include "sound_pas16.h"
#include "sound_sb.h"
#include "sound_sb_dsp.h"
@@ -35,23 +36,25 @@ typedef struct
static SOUND_CARD sound_cards[] =
{
- {"None", "none", NULL},
- {"Adlib", "adlib", &adlib_device},
- {"Adlib", "adlib_mca", &adlib_mca_device},
- {"Sound Blaster 1.0", "sb", &sb_1_device},
- {"Sound Blaster 1.5", "sb1.5", &sb_15_device},
- {"Sound Blaster MCV", "sbmcv", &sb_mcv_device},
- {"Sound Blaster 2.0", "sb2.0", &sb_2_device},
- {"Sound Blaster Pro v1", "sbprov1", &sb_pro_v1_device},
- {"Sound Blaster Pro v2", "sbprov2", &sb_pro_v2_device},
- {"Sound Blaster Pro MCV", "sbpromcv", &sb_pro_mcv_device},
- {"Sound Blaster 16", "sb16", &sb_16_device},
- {"Sound Blaster AWE32", "sbawe32", &sb_awe32_device},
- {"Adlib Gold", "adlibgold", &adgold_device},
- {"Windows Sound System", "wss", &wss_device},
- {"Pro Audio Spectrum 16", "pas16", &pas16_device},
- {"Ensoniq AudioPCI (ES1371)", "es1371", &es1371_device},
- {"Sound Blaster PCI 128", "sbpci128", &es1371_device},
+ {"None", "none", NULL},
+ {"Adlib", "adlib", &adlib_device},
+ {"Adlib", "adlib_mca", &adlib_mca_device},
+ {"Sound Blaster 1.0", "sb", &sb_1_device},
+ {"Sound Blaster 1.5", "sb1.5", &sb_15_device},
+ {"Sound Blaster MCV", "sbmcv", &sb_mcv_device},
+ {"Sound Blaster 2.0", "sb2.0", &sb_2_device},
+ {"Sound Blaster Pro v1", "sbprov1", &sb_pro_v1_device},
+ {"Sound Blaster Pro v2", "sbprov2", &sb_pro_v2_device},
+ {"Sound Blaster Pro MCV", "sbpromcv", &sb_pro_mcv_device},
+ {"Sound Blaster 16", "sb16", &sb_16_device},
+ {"Sound Blaster AWE32", "sbawe32", &sb_awe32_device},
+ {"Adlib Gold", "adlibgold", &adgold_device},
+ {"Windows Sound System", "wss", &wss_device},
+ {"Aztech Sound Galaxy Pro 16 AB (Washington)", "azt2316a", &azt2316a_device},
+ {"Aztech Sound Galaxy Nova 16 Extra (Clinton)", "azt1605", &azt1605_device},
+ {"Pro Audio Spectrum 16", "pas16", &pas16_device},
+ {"Ensoniq AudioPCI (ES1371)", "es1371", &es1371_device},
+ {"Sound Blaster PCI 128", "sbpci128", &es1371_device},
{"", "", NULL}
};
diff --git a/src/sound_ad1848.c b/src/sound_ad1848.c
index abbbc96..91bdcf9 100644
--- a/src/sound_ad1848.c
+++ b/src/sound_ad1848.c
@@ -4,8 +4,10 @@
#include "pic.h"
#include "sound.h"
#include "sound_ad1848.h"
+#include "x86.h"
-static int ad1848_vols[64];
+static int ad1848_vols_6bits[64];
+static uint32_t ad1848_vols_5bits_aux_gain[32];
void ad1848_setirq(ad1848_t *ad1848, int irq)
{
@@ -21,7 +23,7 @@ uint8_t ad1848_read(uint16_t addr, void *p)
{
ad1848_t *ad1848 = (ad1848_t *)p;
uint8_t temp = 0xff;
-// pclog("ad1848_read - addr %04X %04X(%08X):%08X ", addr, CS, cs, pc);
+
switch (addr & 3)
{
case 0: /*Index*/
@@ -34,7 +36,10 @@ uint8_t ad1848_read(uint16_t addr, void *p)
temp = ad1848->status;
break;
}
-// pclog("return %02X\n", temp);
+// if ((addr & 3) == 1 && (ad1848->index & 0x1f) > 0x0f)
+// pclog("ad1848_read_EXTENDED - addr %04X %04X(%08X):%08X return %02X\n", addr, CS, cs, cpu_state.pc, temp);
+// else
+// pclog("ad1848_read - addr %04X %04X(%08X):%08X return %02X\n", addr, CS, cs, cpu_state.pc, temp);
return temp;
}
@@ -42,11 +47,18 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
{
ad1848_t *ad1848 = (ad1848_t *)p;
double freq;
-// pclog("ad1848_write - addr %04X val %02X %04X(%08X):%08X\n", addr, val, CS, cs, pc);
+ uint32_t new_cd_vol_l, new_cd_vol_r;
+// if ((addr & 3) == 0 && (val & 0x1f) > 0x0f)
+// pclog("ad1848_write_EXTENDED - addr %04X val %02X %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc);
+// else
+// pclog("ad1848_write - addr %04X val %02X %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc);
switch (addr & 3)
{
case 0: /*Index*/
- ad1848->index = val & 0xf;
+ if (ad1848->regs[12] & 0x40 && ad1848->type == AD1848_TYPE_CS4231)
+ ad1848->index = val & 0x1f; // cs4231a extended mode enabled
+ else
+ ad1848->index = val & 0x0f; // ad1848/cs4248 mode TODO: some variants/clones DO NOT mirror, just ignore the writes?
ad1848->trd = val & 0x20;
ad1848->mce = val & 0x40;
break;
@@ -67,33 +79,53 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
case 7: freq /= 2560; break;
}
ad1848->freq = freq;
- ad1848->timer_latch = (int)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq));
+ ad1848->timer_latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq));
break;
case 9:
- if (!ad1848->enable && (val & 0x41) == 0x01)
- {
- if (ad1848->timer_latch)
- timer_advance_u64(&ad1848->timer, ad1848->timer_latch);
- else
- timer_advance_u64(&ad1848->timer, TIMER_USEC);
- }
+ if (!ad1848->enable && (val & 0x41) == 0x01)
+ {
+ if (ad1848->timer_latch)
+ timer_set_delay_u64(&ad1848->timer, ad1848->timer_latch);
+ else
+ timer_set_delay_u64(&ad1848->timer, TIMER_USEC);
+ }
ad1848->enable = ((val & 0x41) == 0x01);
if (!ad1848->enable)
- {
- timer_disable(&ad1848->timer);
+ {
+ timer_disable(&ad1848->timer);
ad1848->out_l = ad1848->out_r = 0;
- }
+ }
break;
case 12:
+ ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80;
return;
case 14:
ad1848->count = ad1848->regs[15] | (val << 8);
break;
+ // TODO: see which of the extended registers should be read only
}
ad1848->regs[ad1848->index] = val;
+
+ if (ad1848->type == AD1848_TYPE_CS4231) // TODO: configure CD volume for CS4248/AD1848 too
+ {
+ if (ad1848->regs[0x12] & 0x80)
+ new_cd_vol_l = 0;
+ else
+ new_cd_vol_l = ad1848_vols_5bits_aux_gain[ad1848->regs[0x12] & 0x1f];
+ if (ad1848->regs[0x13] & 0x80)
+ new_cd_vol_r = 0;
+ else
+ new_cd_vol_r = ad1848_vols_5bits_aux_gain[ad1848->regs[0x13] & 0x1f];
+
+ // Apparently there is no master volume to modulate here
+ // (The windows mixer just adjusts all registers at the same
+ // time when the master slider is adjusted)
+ sound_set_cd_volume(new_cd_vol_l, new_cd_vol_r);
+ }
+
break;
case 2:
ad1848->status &= 0xfe;
@@ -122,10 +154,10 @@ static void ad1848_poll(void *p)
if (ad1848->timer_latch)
timer_advance_u64(&ad1848->timer, ad1848->timer_latch);
else
- timer_advance_u64(&ad1848->timer, TIMER_USEC);
+ timer_advance_u64(&ad1848->timer, TIMER_USEC*1000);
ad1848_update(ad1848);
-
+ // TODO: line in, mic, etc...
if (ad1848->enable)
{
int32_t temp;
@@ -155,12 +187,12 @@ static void ad1848_poll(void *p)
if (ad1848->regs[6] & 0x80)
ad1848->out_l = 0;
else
- ad1848->out_l = (ad1848->out_l * ad1848_vols[ad1848->regs[6] & 0x3f]) >> 16;
+ ad1848->out_l = (ad1848->out_l * ad1848_vols_6bits[ad1848->regs[6] & 0x3f]) >> 16;
if (ad1848->regs[7] & 0x80)
ad1848->out_r = 0;
else
- ad1848->out_r = (ad1848->out_r * ad1848_vols[ad1848->regs[7] & 0x3f]) >> 16;
+ ad1848->out_r = (ad1848->out_r * ad1848_vols_6bits[ad1848->regs[7] & 0x3f]) >> 16;
if (ad1848->count < 0)
{
@@ -179,15 +211,17 @@ static void ad1848_poll(void *p)
else
{
ad1848->out_l = ad1848->out_r = 0;
+ sound_set_cd_volume(0, 0);
// pclog("ad1848_poll : not enable\n");
}
}
-void ad1848_init(ad1848_t *ad1848)
+void ad1848_init(ad1848_t *ad1848, int type)
{
int c;
double attenuation;
+ ad1848->type = type;
ad1848->enable = 0;
ad1848->status = 0xcc;
@@ -195,15 +229,24 @@ void ad1848_init(ad1848_t *ad1848)
ad1848->mce = 0x40;
ad1848->regs[0] = ad1848->regs[1] = 0;
- ad1848->regs[2] = ad1848->regs[3] = 0x80;
+ ad1848->regs[2] = ad1848->regs[3] = 0x80; // AZT2316A Line-in
ad1848->regs[4] = ad1848->regs[5] = 0x80;
- ad1848->regs[6] = ad1848->regs[7] = 0x80;
+ ad1848->regs[6] = ad1848->regs[7] = 0x80; // AZT2316A Master?
ad1848->regs[8] = 0;
ad1848->regs[9] = 0x08;
ad1848->regs[10] = ad1848->regs[11] = 0;
- ad1848->regs[12] = 0xa;
+ if (ad1848->type == AD1848_TYPE_CS4248 || ad1848->type == AD1848_TYPE_CS4231)
+ ad1848->regs[12] = 0x8a;
+ else
+ ad1848->regs[12] = 0xa;
ad1848->regs[13] = 0;
ad1848->regs[14] = ad1848->regs[15] = 0;
+
+ if (ad1848->type == AD1848_TYPE_CS4231)
+ {
+ ad1848->regs[0x12] = ad1848->regs[0x13] = 0x80; // AZT2316A CD
+ ad1848->regs[0x1A] = 0x80; // AZT2316A Mic
+ }
ad1848->out_l = 0;
ad1848->out_r = 0;
@@ -220,9 +263,23 @@ void ad1848_init(ad1848_t *ad1848)
attenuation = pow(10, attenuation / 10);
- ad1848_vols[c] = (int)(attenuation * 65536);
-// pclog("ad1848_vols %i = %f %i\n", c, attenuation, ad1848_vols[c]);
+ ad1848_vols_6bits[c] = (int)(attenuation * 65536);
+// pclog("ad1848_vols_6bits %i = %f %i\n", c, attenuation, ad1848_vols_6bits[c]);
}
-
+ for (c = 0; c < 32; c++)
+ {
+ attenuation = 12.0;
+ if (c & 0x01) attenuation -= 1.5;
+ if (c & 0x02) attenuation -= 3.0;
+ if (c & 0x04) attenuation -= 6.0;
+ if (c & 0x08) attenuation -= 12.0;
+ if (c & 0x10) attenuation -= 24.0;
+
+ attenuation = pow(10, attenuation / 10);
+
+ ad1848_vols_5bits_aux_gain[c] = (int)(attenuation * 65536);
+// pclog("ad1848_vols_5bits_aux_gain %i = %f %i\n", c, attenuation, ad1848_vols_5bits_aux_gain[c]);
+ }
+
timer_add(&ad1848->timer, ad1848_poll, ad1848, 0);
}
diff --git a/src/sound_ad1848.h b/src/sound_ad1848.h
index a0c436d..de951d9 100644
--- a/src/sound_ad1848.h
+++ b/src/sound_ad1848.h
@@ -1,9 +1,13 @@
#include "timer.h"
+#define AD1848_TYPE_DEFAULT 0
+#define AD1848_TYPE_CS4248 1
+#define AD1848_TYPE_CS4231 2
+
typedef struct ad1848_t
{
int index;
- uint8_t regs[16];
+ uint8_t regs[32]; // 16 original + 16 CS4231A extensions
uint8_t status;
int trd;
@@ -20,10 +24,12 @@ typedef struct ad1848_t
int freq;
pc_timer_t timer;
- uint64_t timer_latch;
+ uint64_t timer_latch;
int16_t buffer[MAXSOUNDBUFLEN * 2];
int pos;
+
+ int type;
} ad1848_t;
void ad1848_setirq(ad1848_t *ad1848, int irq);
@@ -35,4 +41,4 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p);
void ad1848_update(ad1848_t *ad1848);
void ad1848_speed_changed(ad1848_t *ad1848);
-void ad1848_init(ad1848_t *ad1848);
+void ad1848_init(ad1848_t *ad1848, int type);
diff --git a/src/sound_adlib.c b/src/sound_adlib.c
index 0be5259..da3de33 100644
--- a/src/sound_adlib.c
+++ b/src/sound_adlib.c
@@ -76,7 +76,7 @@ void *adlib_mca_init()
adlib_t *adlib = adlib_init();
io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl);
- mca_add(adlib_mca_read, adlib_mca_write, adlib);
+ mca_add(adlib_mca_read, adlib_mca_write, NULL, adlib);
adlib->pos_regs[0] = 0xd7;
adlib->pos_regs[1] = 0x70;
diff --git a/src/sound_audiopci.c b/src/sound_audiopci.c
index b56b510..21df235 100644
--- a/src/sound_audiopci.c
+++ b/src/sound_audiopci.c
@@ -47,7 +47,8 @@ typedef struct es1371_t
uint32_t addr, addr_latch;
uint16_t count, size;
- uint16_t samp_ct, curr_samp_ct;
+ uint16_t samp_ct;
+ int curr_samp_ct;
pc_timer_t timer;
uint64_t latch;
@@ -129,7 +130,7 @@ const int32_t codec_attn[]=
};
static void es1371_fetch(es1371_t *es1371, int dac_nr);
-static void update_legacy(es1371_t *es1371);
+static void update_legacy(es1371_t *es1371, uint32_t old_legacy_ctrl);
static void es1371_update_irqs(es1371_t *es1371)
{
@@ -352,6 +353,7 @@ static uint32_t es1371_inl(uint16_t port, void *p)
static void es1371_outb(uint16_t port, uint8_t val, void *p)
{
es1371_t *es1371 = (es1371_t *)p;
+ uint32_t old_legacy_ctrl;
// pclog("es1371_outb: port=%04x val=%02x %04x:%08x\n", port, val, cs, cpu_state.pc);
switch (port & 0x3f)
@@ -396,14 +398,16 @@ static void es1371_outb(uint16_t port, uint8_t val, void *p)
nmi = 0;
break;
case 0x1a:
+ old_legacy_ctrl = es1371->legacy_ctrl;
es1371->legacy_ctrl = (es1371->legacy_ctrl & 0xff00ffff) | (val << 16);
- update_legacy(es1371);
+ update_legacy(es1371, old_legacy_ctrl);
break;
case 0x1b:
+ old_legacy_ctrl = es1371->legacy_ctrl;
es1371->legacy_ctrl = (es1371->legacy_ctrl & 0x00ffffff) | (val << 24);
es1371_update_irqs(es1371);
// output = 3;
- update_legacy(es1371);
+ update_legacy(es1371, old_legacy_ctrl);
break;
case 0x20:
@@ -579,8 +583,6 @@ static void es1371_outl(uint16_t port, uint32_t val, void *p)
case 0xc:
es1371->dac[0].size = val & 0xffff;
es1371->dac[0].count = val >> 16;
- if (es1371->dac[0].count)
- es1371->dac[0].count -= 4;
break;
case 0xd:
@@ -722,26 +724,44 @@ static uint8_t capture_read_slave_dma(uint16_t port, void *p)
return 0xff;
}
-static void update_legacy(es1371_t *es1371)
+static void update_legacy(es1371_t *es1371, uint32_t old_legacy_ctrl)
{
- io_removehandler(0x0320, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371);
- io_removehandler(0x0330, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371);
- io_removehandler(0x0340, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371);
- io_removehandler(0x0350, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371);
-
- io_removehandler(0x5300, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371);
- io_removehandler(0xe800, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371);
- io_removehandler(0xf400, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371);
-
- io_removehandler(0x0220, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371);
- io_removehandler(0x0240, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371);
-
- io_removehandler(0x0388, 0x0004, capture_read_adlib,NULL,NULL, capture_write_adlib,NULL,NULL, es1371);
-
- io_removehandler(0x0020, 0x0002, capture_read_master_pic,NULL,NULL, capture_write_master_pic,NULL,NULL, es1371);
- io_removehandler(0x0000, 0x0010, capture_read_master_dma,NULL,NULL, capture_write_master_dma,NULL,NULL, es1371);
- io_removehandler(0x00a0, 0x0002, capture_read_slave_pic,NULL,NULL, capture_write_slave_pic,NULL,NULL, es1371);
- io_removehandler(0x00c0, 0x0020, capture_read_slave_dma,NULL,NULL, capture_write_slave_dma,NULL,NULL, es1371);
+ if (old_legacy_ctrl & LEGACY_CAPTURE_SSCAPE)
+ {
+ switch ((old_legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3)
+ {
+ case 0: io_removehandler(0x0320, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
+ case 1: io_removehandler(0x0330, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
+ case 2: io_removehandler(0x0340, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
+ case 3: io_removehandler(0x0350, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
+ }
+ }
+ if (old_legacy_ctrl & LEGACY_CAPTURE_CODEC)
+ {
+ switch ((old_legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3)
+ {
+ case 0: io_removehandler(0x5300, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break;
+ case 2: io_removehandler(0xe800, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break;
+ case 3: io_removehandler(0xf400, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break;
+ }
+ }
+ if (old_legacy_ctrl & LEGACY_CAPTURE_SB)
+ {
+ if (!(old_legacy_ctrl & LEGACY_SB_ADDR))
+ io_removehandler(0x0220, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371);
+ else
+ io_removehandler(0x0240, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371);
+ }
+ if (old_legacy_ctrl & LEGACY_CAPTURE_ADLIB)
+ io_removehandler(0x0388, 0x0004, capture_read_adlib,NULL,NULL, capture_write_adlib,NULL,NULL, es1371);
+ if (old_legacy_ctrl & LEGACY_CAPTURE_MASTER_PIC)
+ io_removehandler(0x0020, 0x0002, capture_read_master_pic,NULL,NULL, capture_write_master_pic,NULL,NULL, es1371);
+ if (old_legacy_ctrl & LEGACY_CAPTURE_MASTER_DMA)
+ io_removehandler(0x0000, 0x0010, capture_read_master_dma,NULL,NULL, capture_write_master_dma,NULL,NULL, es1371);
+ if (old_legacy_ctrl & LEGACY_CAPTURE_SLAVE_PIC)
+ io_removehandler(0x00a0, 0x0002, capture_read_slave_pic,NULL,NULL, capture_write_slave_pic,NULL,NULL, es1371);
+ if (old_legacy_ctrl & LEGACY_CAPTURE_SLAVE_DMA)
+ io_removehandler(0x00c0, 0x0020, capture_read_slave_dma,NULL,NULL, capture_write_slave_dma,NULL,NULL, es1371);
if (es1371->legacy_ctrl & LEGACY_CAPTURE_SSCAPE)
{
@@ -1101,16 +1121,13 @@ static void es1371_poll(void *p)
es1371_next_sample_filtered(es1371, 0, es1371->dac[0].f_pos ? 16 : 0);
es1371->dac[0].f_pos = (es1371->dac[0].f_pos + 1) & 1;
- es1371->dac[0].curr_samp_ct++;
- if (es1371->dac[0].curr_samp_ct == es1371->dac[0].samp_ct)
+ es1371->dac[0].curr_samp_ct--;
+ if (es1371->dac[0].curr_samp_ct < 0)
{
// pclog("DAC1 IRQ\n");
es1371->int_status |= INT_STATUS_DAC1;
es1371_update_irqs(es1371);
- }
- if (es1371->dac[0].curr_samp_ct > es1371->dac[0].samp_ct)
- {
- es1371->dac[0].curr_samp_ct = 0;
+ es1371->dac[0].curr_samp_ct = es1371->dac[0].samp_ct;
}
}
}
@@ -1134,16 +1151,14 @@ static void es1371_poll(void *p)
es1371_next_sample_filtered(es1371, 1, es1371->dac[1].f_pos ? 16 : 0);
es1371->dac[1].f_pos = (es1371->dac[1].f_pos + 1) & 1;
- es1371->dac[1].curr_samp_ct++;
- if (es1371->dac[1].curr_samp_ct == es1371->dac[1].samp_ct)
+ es1371->dac[1].curr_samp_ct--;
+ if (es1371->dac[1].curr_samp_ct < 0)
{
-// es1371->dac[1].curr_samp_ct = 0;
// pclog("DAC2 IRQ\n");
es1371->int_status |= INT_STATUS_DAC2;
es1371_update_irqs(es1371);
+ es1371->dac[1].curr_samp_ct = es1371->dac[1].samp_ct;
}
- if (es1371->dac[1].curr_samp_ct > es1371->dac[1].samp_ct)
- es1371->dac[1].curr_samp_ct = 0;
}
}
}
diff --git a/src/sound_azt2316a.c b/src/sound_azt2316a.c
new file mode 100644
index 0000000..da41bce
--- /dev/null
+++ b/src/sound_azt2316a.c
@@ -0,0 +1,1620 @@
+/*
+ * TYPE 0x11: (Washington)
+ * Aztech MMPRO16AB,
+ * Aztech Sound Galaxy Pro 16 AB
+ * Aztech Sound Galaxy Washington 16
+ * Packard Bell Sound 16A
+ * ...and other OEM names
+ * FCC ID I38-MMSN824 and others
+ *
+ * TYPE 0x0C: (Clinton)
+ * Aztech Sound Galaxy Nova 16 Extra
+ * Aztech Sound Galaxy Clinton 16
+ * Packard Bell Forte 16
+ * ...and other OEM names
+ *
+ * Also works more or less for drivers of other models with the same chipsets.
+ *
+ * Copyright (c) 2020 Eluan Costa Miranda All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * =============================================================================
+ *
+ * The CS4248 DSP used is pin and software compatible with the AD1848.
+ * I also have one of these cards with a CS4231. The driver talks to the
+ * emulated card as if it was a CS4231 and I still don't know how to tell the
+ * drivers to see the CS4248. The CS4231 more advanced features are NOT used,
+ * just the new input/output channels. Apparently some drivers are hardcoded
+ * for one or the other, so there is an option for this.
+ *
+ * There is lots more to be learned form the Win95 drivers. The Linux driver is
+ * very straightforward and doesn't do much.
+ *
+ * Recording and voice modes in the windows mixer still do nothing in PCem, so
+ * this is missing.
+ *
+ * There is a jumper to load the startup configuration from an EEPROM. This is
+ * implemented, so any software-configured parameters will be saved.
+ *
+ * The CD-ROM interface commands are just ignored, along with gameport.
+ * The MPU401 is always enabled.
+ * The OPL3 is always active in some (all?) drivers/cards, so there is no
+ * configuration for this.
+ *
+ * Tested with DOS (driver installation, tools, diagnostics), Win3.1 (driver
+ * installation, tools), Win95 (driver auto-detection), Win NT 3.1 (driver
+ * installation), lots of games.
+ *
+ * I consider type 0x11 (Washington) to be very well tested. Type 0x0C (Clinton)
+ * wasn't fully tested, but works well for WSS/Windows. BEWARE that there are
+ * *too many* driver types and OEM versions for each card. Maybe yours isn't
+ * emulated or you have the wrong driver. Some features of each card may work
+ * when using wrong drivers. CODEC selection is also important.
+ *
+ * Any updates to the WSS and SBPROV2 sound cards should be synced here when
+ * appropriate. The WSS was completely cloned here, while the SBPROV2 tends
+ * to call the original functions, except for initialization.
+ *
+ * TODO/Notes:
+ * -Some stuff still not understood on I/O addresses 0x624 and 0x530-0x533.
+ * -Is the CS42xx dither mode used anywhere? Implement.
+ * -What are the voice commands mode in Win95 mixer again?
+ * -Configuration options not present on Aztech's CONFIG.EXE have been commented
+ * out or deleted. Other types of cards with this chipset may need them.
+ * -Sfademo on the Descent CD fails under Win95, works under DOS, see if it
+ * happens on real hardware (and OPL3 stops working after the failure)
+ * -There appears to be some differences in sound volumes bertween MIDI,
+ * SBPROV2, WSS and OPL3? Also check relationship between the SBPROV2 mixer and
+ * the WSS mixer! Are they independent? Current mode selects which mixer? Are
+ * they entangled?
+ * -Check real hardware to see if advanced, mic boost, etc appear in the mixer?
+ * -CD-ROM driver shipped with the card (SGIDECD.SYS) checks for model strings.
+ * I have implemented mine (AZtech CDA 468-02I 4x) in PCem.
+ * -Descent 2 W95 version can't start cd music. Happens on real hardware.
+ * Explanation further below.
+ * -DOSQuake and Descent 2 DOS cd music do not work under Win95. The mode
+ * selects get truncated and send all zeros for output channel selection and
+ * volume, Descent 2 also has excess zeros! This is a PCem bug, happens on all
+ * sound cards. CD audio works in Winquake and Descent 2 DOS setup program.
+ * -DOSQuake CD audio works under DOS with VIDE-CDD.SYS and SGIDECD.SYS.
+ * Descent 2 DOS is still mute but volume selection appears to be working.
+ * Descent 2 fails to launch with SGIDECD.SYS with "Device failed to request
+ * command". SGIDECD.SYS is the CD-ROM driver included with the sound card
+ * drivers. My real CD-ROM drive can't read anything so I can't check the
+ * real behavior of this driver.
+ * -Some cards just have regular IDE ports while other have proprietary ports.
+ * The regular IDE ports just have a option to enable an almost-generic CD-ROM
+ * driver in CONFIG.SYS/AUTOEXEC.BAT (like SGIDECD.SYS) and the onboard port
+ * is enabled/disabled by jumpers. The proprietary ones also have
+ * address/dma/irq settings. Since the configuration options are ignored here,
+ * this behaves like a card with a regular interface disabled by jumper and
+ * the configuration just adds/removes the drivers (which will see other IDE
+ * interfaces present) from the boot process.
+ * -Continue reverse engineering to see if the AZT1605 shares the SB DMA with
+ * WSS or if it is set separately by the TSR loaded on boot. Currently it is
+ * only set by PCem config and then saved to EEPROM (which would make it fixed
+ * if loading from EEPROM too).
+ * -Related to the previous note, part of the SBPROV2 emulation on the CLINTON
+ * family appears to be implemented with a TSR. It's better to remove the TSR
+ * for now. I need to investigate this. Mixer is also weird under DOS (and
+ * wants to save to EEPROM? I don't think the WASHINGTON does this).
+ * -VOLSET.EXE /S:S is supposed to be a no-op on the MMP16AB?
+ * -Search for TODO in this file. :-)
+ *
+ * Misc things I use to test for regressions: Windows sounds, Descent under
+ * dos/windows, Descent 2 dos/windows (+ cd music option), Descent 2 W95 + cd
+ * music, Age of Empires (CD + Midi), cd-audio under Windows + volume,
+ * cd-audio under dos + volume, Aztech diagnose.exe, Aztech volset /M:3 then
+ * volset /D, Aztech setmode, mixer (volume + balance) under dos and windows,
+ * DOSQuake under dos and windows (+ cd music and volumes, + Winquake).
+ *
+ * Reason for Descent 2 Win95 CD-Audio not working:
+ * The game calls auxGetNumDevs() to check if any of the AUX devices has
+ * caps.wTechnology == AUXCAPS_CDAUDIO, but this fails because the Aztech
+ * Win95 driver only returns a "Line-In" device. I'm not aware of any other
+ * game that does this and this is completely unnecessary. Other games that
+ * play cd audio correctly have the exact *same* initialization code, minus
+ * this check that only Descent 2 Win95 does. It would work if it just skipped
+ * this check and progressed with calling mciSendCommand() with
+ * mciOpenParms.lpstrDeviceType = "cdaudio", like other games do. There are
+ * some sound cards listed as incompatible in the game's README.TXT file that
+ * are probably due to this.
+ */
+
+#include
+#include
+#include "ibm.h"
+
+#include "device.h"
+#include "dma.h"
+#include "io.h"
+#include "nvr.h"
+#include "pic.h"
+#include "sound.h"
+#include "sound_ad1848.h"
+#include "sound_azt2316a.h"
+#include "sound_opl.h"
+#include "sound_sb.h"
+#include "sound_sb_dsp.h"
+
+/*530, 11, 3 - 530=23*/
+/*530, 11, 1 - 530=22*/
+/*530, 11, 0 - 530=21*/
+/*530, 10, 1 - 530=1a*/
+/*530, 10, 0 - 530=19*/
+/*530, 9, 1 - 530=12*/
+/*530, 7, 1 - 530=0a*/
+/*604, 11, 1 - 530=22*/
+/*e80, 11, 1 - 530=22*/
+/*f40, 11, 1 - 530=22*/
+
+
+static int azt2316a_wss_dma[4] = {0, 0, 1, 3};
+static int azt2316a_wss_irq[8] = {5, 7, 9, 10, 11, 12, 14, 15}; /* W95 only uses 7-10, others may be wrong */
+//static uint16_t azt2316a_wss_addr[4] = {0x530, 0x604, 0xe80, 0xf40};
+
+typedef struct azt2316a_t
+{
+ int type;
+ int wss_interrupt_after_config;
+
+ uint8_t wss_config;
+
+ uint16_t cur_addr, cur_wss_addr, cur_mpu401_addr;
+
+ uint8_t cur_irq, cur_dma, opl_emu; // sb
+ uint8_t cur_wss_enabled, cur_wss_irq, cur_wss_dma;
+ uint8_t cur_mpu401_irq;
+
+ uint32_t config_word;
+ uint32_t config_word_unlocked;
+
+ uint8_t cur_mode;
+
+ ad1848_t ad1848;
+
+ sb_t *sb;
+} azt2316a_t;
+
+uint8_t azt2316a_wss_read(uint16_t addr, void *p)
+{
+ azt2316a_t *azt2316a = (azt2316a_t *)p;
+ uint8_t temp;
+// pclog("azt2316a_read - addr %04X\n", addr);
+ // TODO: when windows is initializing, writing 0x48, 0x58 and 0x60 to
+ // 0x530 makes reading from 0x533 return 0x44, but writing 0x50
+ // makes this return 0x04. Why?
+ if (addr & 1)
+ temp = 4 | (azt2316a->wss_config & 0x40);
+ else
+ temp = 4 | (azt2316a->wss_config & 0xC0);
+// pclog("return %02X\n", temp);
+ return temp;
+}
+
+void azt2316a_wss_write(uint16_t addr, uint8_t val, void *p)
+{
+ int interrupt = 0;
+ azt2316a_t *azt2316a = (azt2316a_t *)p;
+// pclog("azt2316a_write - addr %04X val %02X\n", addr, val);
+
+ if (azt2316a->wss_interrupt_after_config)
+ if ((azt2316a->wss_config & 0x40) && !(val & 0x40)) // TODO: is this the right edge?
+ interrupt = 1;
+
+ azt2316a->wss_config = val;
+ azt2316a->cur_wss_dma = azt2316a_wss_dma[val & 3];
+ azt2316a->cur_wss_irq = azt2316a_wss_irq[(val >> 3) & 7];
+ ad1848_setdma(&azt2316a->ad1848, azt2316a_wss_dma[val & 3]);
+ ad1848_setirq(&azt2316a->ad1848, azt2316a_wss_irq[(val >> 3) & 7]);
+
+ if (interrupt)
+ picint(1 << azt2316a->cur_wss_irq);
+}
+
+// generate a config word based on current settings
+void azt1605_create_config_word(void *p)
+{
+ azt2316a_t *azt2316a = (azt2316a_t *)p;
+ uint32_t temp = 0;
+
+ // not implemented / hardcoded
+ uint8_t game_enable = 1;
+ uint8_t mpu401_enable = 1;
+ uint8_t cd_type = 0; // TODO: see if the cd-rom was originally connected there on the real machines emulated by PCem (Packard Bell Legend 100CD, Itautec Infoway Multimidia, etc)
+ uint8_t cd_dma8 = -1;
+ uint8_t cd_irq = 0;
+
+ switch (azt2316a->cur_addr)
+ {
+ case 0x220:
+ // do nothing
+ //temp += 0 << 0;
+ break;
+ case 0x240:
+ temp += 1 << 0;
+ break;
+/*
+ case 0x260: // TODO: INVALID?
+ temp += 2 << 0;
+ break;
+ case 0x280: // TODO: INVALID?
+ temp += 3 << 0;
+ break;
+*/
+ default:
+ fatal("Bad AZT1605 addr %04X\n", azt2316a->cur_addr);
+ }
+ switch (azt2316a->cur_irq)
+ {
+ case 2:
+ temp += 1 << 8;
+ break;
+ case 3:
+ temp += 1 << 9;
+ break;
+ case 5:
+ temp += 1 << 10;
+ break;
+ case 7:
+ temp += 1 << 11;
+ break;
+ default:
+ fatal("Bad AZT1605 irq %02X\n", azt2316a->cur_irq);
+ }
+ switch (azt2316a->cur_wss_addr)
+ {
+ case 0x530:
+ // do nothing
+ //temp += 0 << 16;
+ break;
+ case 0x604:
+ temp += 1 << 16;
+ break;
+ case 0xE80:
+ temp += 2 << 16;
+ break;
+ case 0xF40:
+ temp += 3 << 16;
+ break;
+ default:
+ fatal("Bad AZT1605 WSS addr %04X\n", azt2316a->cur_wss_addr);
+ }
+ if (azt2316a->cur_wss_enabled)
+ temp += 1 << 18;
+ if (game_enable)
+ temp += 1 << 4;
+ switch (azt2316a->cur_mpu401_addr)
+ {
+ case 0x300:
+ // do nothing
+ //temp += 0 << 2;
+ break;
+ case 0x330:
+ temp += 1 << 2;
+ break;
+ default:
+ fatal("Bad AZT1605 MPU401 addr %04X\n", azt2316a->cur_mpu401_addr);
+ }
+ if (mpu401_enable)
+ temp += 1 << 3;
+ switch (cd_type)
+ {
+ case 0: // disabled
+ // do nothing
+ //temp += 0 << 5;
+ break;
+ case 1: // panasonic
+ temp += 1 << 5;
+ break;
+ case 2: // mitsumi/sony/aztech
+ temp += 2 << 5;
+ break;
+ case 3: // all enabled
+ temp += 3 << 5;
+ break;
+ case 4: // unused
+ temp += 4 << 5;
+ break;
+ case 5: // unused
+ temp += 5 << 5;
+ break;
+ case 6: // unused
+ temp += 6 << 5;
+ break;
+ case 7: // unused
+ temp += 7 << 5;
+ break;
+ default:
+ fatal("Bad AZT1605 CD type %02X\n", cd_type);
+ }
+ switch (cd_dma8)
+ {
+ case 0xFF: // -1
+ // do nothing
+ //temp += 0 << 22;
+ break;
+ case 0:
+ temp += 1 << 22;
+ break;
+ case 1:
+ temp += 2 << 22;
+ break;
+ case 3:
+ temp += 3 << 22;
+ break;
+ default:
+ fatal("Bad AZT1605 cd dma8 %02X\n", cd_dma8);
+
+ }
+ switch (azt2316a->cur_mpu401_irq)
+
+ {
+ case 2:
+ temp += 1 << 12;
+ break;
+ case 3:
+ temp += 1 << 13;
+ break;
+ case 5:
+ temp += 1 << 14;
+ break;
+ case 7:
+ temp += 1 << 15;
+ break;
+ default:
+ fatal("Bad AZT1605 mpu401 irq %02X\n", azt2316a->cur_mpu401_irq);
+ }
+ switch (cd_irq)
+ {
+ case 0: // disabled
+ // do nothing
+ break;
+ case 11:
+ temp += 1 << 19;
+ break;
+ case 12:
+ temp += 1 << 20;
+ break;
+ case 15:
+ temp += 1 << 21;
+ break;
+ default:
+ fatal("Bad AZT1605 cd irq %02X\n", cd_irq);
+ }
+
+ azt2316a->config_word = temp;
+}
+void azt2316a_create_config_word(void *p)
+{
+ azt2316a_t *azt2316a = (azt2316a_t *)p;
+ uint32_t temp = 0;
+
+ // not implemented / hardcoded
+ uint8_t game_enable = 1;
+ uint8_t mpu401_enable = 1;
+ uint16_t cd_addr = 0x310;
+ uint8_t cd_type = 0; // TODO: see if the cd-rom was originally connected there on the real machines emulated by PCem (Packard Bell Legend 100CD, Itautec Infoway Multimidia, etc)
+ uint8_t cd_dma8 = -1;
+ uint8_t cd_dma16 = -1;
+ uint8_t cd_irq = 15;
+
+ if (azt2316a->type == SB_SUBTYPE_CLONE_AZT1605_0X0C)
+ {
+ azt1605_create_config_word(p);
+ return;
+ }
+
+ switch (azt2316a->cur_addr)
+ {
+ case 0x220:
+ // do nothing
+ //temp += 0 << 0;
+ break;
+ case 0x240:
+ temp += 1 << 0;
+ break;
+/*
+ case 0x260: // TODO: INVALID?
+ temp += 2 << 0;
+ break;
+ case 0x280: // TODO: INVALID?
+ temp += 3 << 0;
+ break;
+*/
+ default:
+ fatal("Bad AZT2316A addr %04X\n", azt2316a->cur_addr);
+ }
+ switch (azt2316a->cur_irq)
+ {
+ case 2:
+ temp += 1 << 2;
+ break;
+ case 5:
+ temp += 1 << 3;
+ break;
+ case 7:
+ temp += 1 << 4;
+ break;
+ case 10:
+ temp += 1 << 5;
+ break;
+ default:
+ fatal("Bad AZT2316A irq %02X\n", azt2316a->cur_irq);
+ }
+ switch (azt2316a->cur_dma)
+ {
+/*
+ // TODO: INVALID?
+ case 0xFF: // -1
+ // do nothing
+ //temp += 0 << 6;
+ break;
+*/
+ case 0:
+ temp += 1 << 6;
+ break;
+ case 1:
+ temp += 2 << 6;
+ break;
+ case 3:
+ temp += 3 << 6;
+ break;
+ default:
+ fatal("Bad AZT2316A dma %02X\n", azt2316a->cur_dma);
+ }
+ switch (azt2316a->cur_wss_addr)
+ {
+ case 0x530:
+ // do nothing
+ //temp += 0 << 8;
+ break;
+ case 0x604:
+ temp += 1 << 8;
+ break;
+ case 0xE80:
+ temp += 2 << 8;
+ break;
+ case 0xF40:
+ temp += 3 << 8;
+ break;
+ default:
+ fatal("Bad AZT2316A WSS addr %04X\n", azt2316a->cur_wss_addr);
+ }
+ if (azt2316a->cur_wss_enabled)
+ temp += 1 << 10;
+ if (game_enable)
+ temp += 1 << 11;
+ switch (azt2316a->cur_mpu401_addr)
+ {
+ case 0x300:
+ // do nothing
+ //temp += 0 << 12;
+ break;
+ case 0x330:
+ temp += 1 << 12;
+ break;
+ default:
+ fatal("Bad AZT2316A MPU401 addr %04X\n", azt2316a->cur_mpu401_addr);
+ }
+ if (mpu401_enable)
+ temp += 1 << 13;
+ switch (cd_addr)
+ {
+ case 0x310:
+ // do nothing
+ //temp += 0 << 14;
+ break;
+ case 0x320:
+ temp += 1 << 14;
+ break;
+ case 0x340:
+ temp += 2 << 14;
+ break;
+ case 0x350:
+ temp += 3 << 14;
+ break;
+ default:
+ fatal("Bad AZT2316A CD addr %04X\n", cd_addr);
+ }
+ switch (cd_type)
+ {
+ case 0: // disabled
+ // do nothing
+ //temp += 0 << 16;
+ break;
+ case 1: // panasonic
+ temp += 1 << 16;
+ break;
+ case 2: // sony
+ temp += 2 << 16;
+ break;
+ case 3: // mitsumi
+ temp += 3 << 16;
+ break;
+ case 4: // aztech
+ temp += 4 << 16;
+ break;
+ case 5: // unused
+ temp += 5 << 16;
+ break;
+ case 6: // unused
+ temp += 6 << 16;
+ break;
+ case 7: // unused
+ temp += 7 << 16;
+ break;
+ default:
+ fatal("Bad AZT2316A CD type %02X\n", cd_type);
+ }
+ switch (cd_dma8)
+ {
+ case 0xFF: // -1
+ // do nothing
+ //temp += 0 << 20;
+ break;
+ case 0:
+ temp += 1 << 20;
+ break;
+/*
+ case 1: // TODO: INVALID?
+ temp += 2 << 20;
+ break;
+*/
+ case 3:
+ temp += 3 << 20;
+ break;
+ default:
+ fatal("Bad AZT2316A cd dma8 %02X\n", cd_dma8);
+ }
+ switch (cd_dma16)
+ {
+ case 0xFF: // -1
+ // do nothing
+ //temp += 0 << 22;
+ break;
+ case 5:
+ temp += 1 << 22;
+ break;
+ case 6:
+ temp += 2 << 22;
+ break;
+ case 7:
+ temp += 3 << 22;
+ break;
+ default:
+ fatal("Bad AZT2316A cd dma16 %02X\n", cd_dma16);
+ }
+ switch (azt2316a->cur_mpu401_irq)
+
+ {
+ case 2:
+ temp += 1 << 24;
+ break;
+ case 5:
+ temp += 1 << 25;
+ break;
+ case 7:
+ temp += 1 << 26;
+ break;
+ case 10:
+ temp += 1 << 27;
+ break;
+ default:
+ fatal("Bad AZT2316A mpu401 irq %02X\n", azt2316a->cur_mpu401_irq);
+ }
+ switch (cd_irq)
+ {
+ case 5:
+ temp += 1 << 28;
+ break;
+ case 11:
+ temp += 1 << 29;
+ break;
+ case 12:
+ temp += 1 << 30;
+ break;
+ case 15:
+ temp += 1 << 31;
+ break;
+ default:
+ fatal("Bad AZT2316A cd irq %02X\n", cd_irq);
+ }
+
+ azt2316a->config_word = temp;
+}
+
+uint8_t azt2316a_config_read(uint16_t addr, void *p)
+{
+ azt2316a_t *azt2316a = (azt2316a_t *)p;
+ uint8_t temp;
+// pclog("azt2316a_config_read - addr %04X\n", addr);
+
+ // Some WSS config here + config change enable bit
+ // (setting bit 7 and writing back)
+ if (addr == azt2316a->cur_addr + 0x404)
+ {
+ // TODO: what is the real meaning of the read value?
+ // I got a mention of bit 0x10 for WSS from disassembling the source
+ // code of the driver, and when playing with the I/O ports on real
+ // hardware after doing some configuration, but didn't dig into it.
+ // Bit 0x08 seems to be a busy flag and generates a timeout
+ // (continuous re-reading when initializing windows 98)
+ temp = azt2316a->cur_mode ? 0x07 : 0x0F;
+ if (azt2316a->config_word_unlocked)
+ temp |= 0x80;
+ }
+ else
+ {
+ // Rest of config. These are documented in the Linux driver.
+ switch (addr & 0x3)
+ {
+ case 0:
+ temp = azt2316a->config_word & 0xFF;
+ break;
+ case 1:
+ temp = (azt2316a->config_word >> 8) & 0xFF;
+ break;
+ case 2:
+ temp = (azt2316a->config_word >> 16) & 0xFF;
+ break;
+ case 3:
+ temp = (azt2316a->config_word >> 24) & 0xFF;
+ break;
+ }
+ }
+
+// pclog("return %02X\n", temp);
+ return temp;
+}
+
+void azt1605_config_write(uint16_t addr, uint8_t val, void *p)
+{
+ azt2316a_t *azt2316a = (azt2316a_t *)p;
+ uint8_t temp;
+// pclog("azt2316a_config_write - addr %04X val %02X\n", addr, val);
+
+ if (addr == azt2316a->cur_addr + 0x404)
+ {
+ if (val & 0x80)
+ azt2316a->config_word_unlocked = 1;
+ else
+ azt2316a->config_word_unlocked = 0;
+ }
+ else if (azt2316a->config_word_unlocked)
+ {
+ if (val == 0xFF) // TODO: check if this still happens on eeprom.sys after having more complete emulation!
+ return;
+ switch (addr & 0x3)
+ {
+ case 0:
+ azt2316a->config_word = (azt2316a->config_word & 0xFFFFFF00) + val;
+
+ temp = val & 0x3;
+ if (temp == 0)
+ azt2316a->cur_addr = 0x220;
+ else if (temp == 1)
+ azt2316a->cur_addr = 0x240;
+/*
+ else if (temp == 2)
+ azt2316a->cur_addr = 0x260; // TODO: INVALID
+ else if (temp == 3)
+ azt2316a->cur_addr = 0x280; // TODO: INVALID
+*/
+
+ if (val & 0x4)
+ azt2316a->cur_mpu401_addr = 0x330;
+ else
+ azt2316a->cur_mpu401_addr = 0x300;
+
+ // mpu401_enabled is harcoded
+ //if (val & 0x8)
+ // azt2316a->cur_mpu401_enabled = 1;
+ //else
+ // azt2316a->cur_mpu401_enabled = 0;
+
+ // game_enabled is hardcoded
+ //if (val & 0x10)
+ // azt2316a->cur_game_enabled = 1;
+ //else
+ // azt2316a->cur_game_enabled = 0;
+
+ // cd_type is hardcoded
+ //azt2316a->cur_cd_type = (val >> 5) & 0x7;
+ break;
+ case 1:
+ azt2316a->config_word = (azt2316a->config_word & 0xFFFF00FF) + (val << 8);
+
+ if (val & 0x1)
+ azt2316a->cur_irq = 2;
+ else if (val & 0x2)
+ azt2316a->cur_irq = 3;
+ else if (val & 0x4)
+ azt2316a->cur_irq = 5;
+ else if (val & 0x8)
+ azt2316a->cur_irq = 7;
+ // else undefined?
+
+ if (val & 0x10)
+ azt2316a->cur_mpu401_irq = 2;
+ else if (val & 0x20)
+ azt2316a->cur_mpu401_irq = 3;
+ else if (val & 0x40)
+ azt2316a->cur_mpu401_irq = 5;
+ else if (val & 0x80)
+ azt2316a->cur_mpu401_irq = 7;
+ // else undefined?
+ break;
+ case 2:
+ azt2316a->config_word = (azt2316a->config_word & 0xFF00FFFF) + (val << 16);
+
+ io_removehandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a);
+ io_removehandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848);
+
+ temp = val & 0x3;
+ if (temp == 0)
+ azt2316a->cur_wss_addr = 0x530;
+ else if (temp == 1)
+ azt2316a->cur_wss_addr = 0x604;
+ else if (temp == 2)
+ azt2316a->cur_wss_addr = 0xE80;
+ else if (temp == 3)
+ azt2316a->cur_wss_addr = 0xF40;
+
+ io_sethandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a);
+ io_sethandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848);
+
+ // no actual effect
+ if (val & 0x4)
+ azt2316a->cur_wss_enabled = 1;
+ else
+ azt2316a->cur_wss_enabled = 0;
+
+ // cd_irq is hardcoded
+ //if (val & 0x8)
+ // azt2316a->cur_cd_irq = 11;
+ //else if (val & 0x10)
+ // azt2316a->cur_cd_irq = 12;
+ //else if (val & 0x20)
+ // azt2316a->cur_cd_irq = 15;
+ // else disable?
+
+ // cd_dma8 is hardcoded
+ //temp = (val >> 6) & 0x3;
+ //if (temp == 0)
+ // azt2316a->cur_cd_dma8 = -1;
+ //else if (temp == 1)
+ // azt2316a->cur_cd_dma8 = 0;
+ //else if (temp == 3)
+ // azt2316a->cur_cd_dma8 = 3;
+ //else error
+ break;
+ case 3:
+ break;
+ }
+ // update sbprov2 configs
+ sb_dsp_setaddr(&azt2316a->sb->dsp, azt2316a->cur_addr);
+ sb_dsp_setirq(&azt2316a->sb->dsp, azt2316a->cur_irq);
+ sb_dsp_setdma8(&azt2316a->sb->dsp, azt2316a->cur_dma);
+
+ mpu401_uart_update_addr(&azt2316a->sb->mpu, azt2316a->cur_mpu401_addr);
+ mpu401_uart_update_irq(&azt2316a->sb->mpu, azt2316a->cur_mpu401_irq);
+ }
+}
+void azt2316a_config_write(uint16_t addr, uint8_t val, void *p)
+{
+ azt2316a_t *azt2316a = (azt2316a_t *)p;
+ uint8_t temp;
+// pclog("azt2316a_config_write - addr %04X val %02X\n", addr, val);
+
+ if (azt2316a->type == SB_SUBTYPE_CLONE_AZT1605_0X0C)
+ {
+ azt1605_config_write(addr, val, p);
+ return;
+ }
+
+ if (addr == azt2316a->cur_addr + 0x404)
+ {
+ if (val & 0x80)
+ azt2316a->config_word_unlocked = 1;
+ else
+ azt2316a->config_word_unlocked = 0;
+ }
+ else if (azt2316a->config_word_unlocked)
+ {
+ if (val == 0xFF) // TODO: check if this still happens on eeprom.sys after having more complete emulation!
+ return;
+ switch (addr & 0x3)
+ {
+ case 0:
+ azt2316a->config_word = (azt2316a->config_word & 0xFFFFFF00) + val;
+
+ temp = val & 0x3;
+ if (temp == 0)
+ azt2316a->cur_addr = 0x220;
+ else if (temp == 1)
+ azt2316a->cur_addr = 0x240;
+/*
+ else if (temp == 2)
+ azt2316a->cur_addr = 0x260; // TODO: INVALID
+ else if (temp == 3)
+ azt2316a->cur_addr = 0x280; // TODO: INVALID
+*/
+
+ if (val & 0x4)
+ azt2316a->cur_irq = 2;
+ else if (val & 0x8)
+ azt2316a->cur_irq = 5;
+ else if (val & 0x10)
+ azt2316a->cur_irq = 7;
+ else if (val & 0x20)
+ azt2316a->cur_irq = 10;
+ // else undefined?
+
+ temp = (val >> 6) & 0x3;
+/*
+ if (temp == 0)
+ azt2316a->cur_dma = -1; // TODO: INVALID?
+ else */if (temp == 1)
+ azt2316a->cur_dma = 0;
+ else if (temp == 2)
+ azt2316a->cur_dma = 1;
+ else if (temp == 3)
+ azt2316a->cur_dma = 3;
+ break;
+ case 1:
+ azt2316a->config_word = (azt2316a->config_word & 0xFFFF00FF) + (val << 8);
+
+ io_removehandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a);
+ io_removehandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848);
+
+ temp = val & 0x3;
+ if (temp == 0)
+ azt2316a->cur_wss_addr = 0x530;
+ else if (temp == 1)
+ azt2316a->cur_wss_addr = 0x604;
+ else if (temp == 2)
+ azt2316a->cur_wss_addr = 0xE80;
+ else if (temp == 3)
+ azt2316a->cur_wss_addr = 0xF40;
+
+ io_sethandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a);
+ io_sethandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848);
+
+ // no actual effect
+ if (val & 0x4)
+ azt2316a->cur_wss_enabled = 1;
+ else
+ azt2316a->cur_wss_enabled = 0;
+
+ // game_enabled is hardcoded
+ //if (val & 0x8)
+ // azt2316a->cur_game_enabled = 1;
+ //else
+ // azt2316a->cur_game_enabled = 0;
+
+ if (val & 0x10)
+ azt2316a->cur_mpu401_addr = 0x330;
+ else
+ azt2316a->cur_mpu401_addr = 0x300;
+
+ // mpu401_enabled is harcoded
+ //if (val & 0x20)
+ // azt2316a->cur_mpu401_enabled = 1;
+ //else
+ // azt2316a->cur_mpu401_enabled = 0;
+
+ // cd_addr is hardcoded
+ //temp = (val >> 6) & 0x3;
+ //if (temp == 0)
+ // azt2316a->cur_cd_addr = 0x310;
+ //else if (temp == 1)
+ // azt2316a->cur_cd_addr = 0x320;
+ //else if (temp == 2)
+ // azt2316a->cur_cd_addr = 0x340;
+ //else if (temp == 3)
+ // azt2316a->cur_cd_addr = 0x350;
+ break;
+ case 2:
+ azt2316a->config_word = (azt2316a->config_word & 0xFF00FFFF) + (val << 16);
+
+ // cd_type is hardcoded
+ //azt2316a->cur_cd_type = val & 0x7;
+
+ // cd_dma8 is hardcoded
+ //temp = (val >> 4) & 0x3;
+ //if (temp == 0)
+ // azt2316a->cur_cd_dma8 = -1;
+ //else if (temp == 1)
+ // azt2316a->cur_cd_dma8 = 0;
+ //else if (temp == 2)
+ // azt2316a->cur_cd_dma8 = 1;
+ //else if (temp == 3)
+ // azt2316a->cur_cd_dma8 = 3;
+
+ // cd_dma16 is hardcoded
+ //temp = (val >> 6) & 0x3;
+ //if (temp == 0)
+ // azt2316a->cur_cd_dma16 = -1;
+ //else if (temp == 1)
+ // azt2316a->cur_cd_dma16 = 5;
+ //else if (temp == 2)
+ // azt2316a->cur_cd_dma16 = 6;
+ //else if (temp == 3)
+ // azt2316a->cur_cd_dma16 = 7;
+ break;
+ case 3:
+ azt2316a->config_word = (azt2316a->config_word & 0x00FFFFFF) + (val << 24);
+
+ if (val & 0x1)
+ azt2316a->cur_mpu401_irq = 2;
+ else if (val & 0x2)
+ azt2316a->cur_mpu401_irq = 5;
+ else if (val & 0x4)
+ azt2316a->cur_mpu401_irq = 7;
+ else if (val & 0x8)
+ azt2316a->cur_mpu401_irq = 10;
+ // else undefined?
+
+ // cd_irq is hardcoded
+ //if (val & 0x10)
+ // azt2316a->cur_cd_irq = 5;
+ //else if (val & 0x20)
+ // azt2316a->cur_cd_irq = 11;
+ //else if (val & 0x40)
+ // azt2316a->cur_cd_irq = 12;
+ //else if (val & 0x80)
+ // azt2316a->cur_cd_irq = 15;
+ // else undefined?
+ break;
+ }
+ // update sbprov2 configs
+ sb_dsp_setaddr(&azt2316a->sb->dsp, azt2316a->cur_addr);
+ sb_dsp_setirq(&azt2316a->sb->dsp, azt2316a->cur_irq);
+ sb_dsp_setdma8(&azt2316a->sb->dsp, azt2316a->cur_dma);
+
+ mpu401_uart_update_addr(&azt2316a->sb->mpu, azt2316a->cur_mpu401_addr);
+ mpu401_uart_update_irq(&azt2316a->sb->mpu, azt2316a->cur_mpu401_irq);
+ }
+}
+
+// How it behaves when one or another is activated may affect games auto-detecting (and will also use more of the limited system resources!)
+void azt2316a_enable_wss(uint8_t enable, void *p)
+{
+ azt2316a_t *azt2316a = (azt2316a_t *)p;
+
+ if (enable)
+ {
+ azt2316a->cur_mode = 1;
+ if (!azt2316a->cur_wss_enabled)
+ {
+// apparently it doesn't work like this!
+// azt2316a->cur_wss_enabled = 1;
+// azt2316a->config_word |= 1 << 10;
+ }
+ }
+ else
+ {
+ azt2316a->cur_mode = 0;
+ if (azt2316a->cur_wss_enabled)
+ {
+// apparently it doesn't work like this!
+// azt2316a->cur_wss_enabled = 0;
+// azt2316a->config_word &= 0xFFFFFFFF - (1 << 10);
+ }
+ }
+}
+
+static void azt2316a_get_buffer(int32_t *buffer, int len, void *p)
+{
+ azt2316a_t *azt2316a = (azt2316a_t *)p;
+
+ int c;
+
+ // wss part
+ ad1848_update(&azt2316a->ad1848);
+ for (c = 0; c < len * 2; c++)
+ {
+ buffer[c] += (azt2316a->ad1848.buffer[c] / 2);
+ }
+
+ azt2316a->ad1848.pos = 0;
+
+ // sbprov2 part
+ sb_get_buffer_sbpro(buffer, len, azt2316a->sb);
+}
+
+void *azt_common_init(const int type, char *nvr_filename)
+{
+ int i;
+ int loaded_from_eeprom = 0;
+ uint16_t addr_setting;
+ uint8_t read_eeprom[AZTECH_EEPROM_SIZE];
+ azt2316a_t *azt2316a = malloc(sizeof(azt2316a_t));
+ memset(azt2316a, 0, sizeof(azt2316a_t));
+
+ // load configs from eeprom
+ FILE *f;
+ f = nvrfopen(nvr_filename, "rb");
+ if (f)
+ {
+ uint8_t checksum = 0x7F;
+ uint8_t saved_checksum;
+ size_t res; // avoid warning
+
+ res = fread(read_eeprom, AZTECH_EEPROM_SIZE, 1, f);
+ for (i = 0; i < AZTECH_EEPROM_SIZE; i++)
+ checksum += read_eeprom[i];
+
+ res = fread(&saved_checksum, sizeof(saved_checksum), 1, f);
+ (void)res;
+
+ fclose(f);
+
+ if (checksum == saved_checksum)
+ loaded_from_eeprom = 1;
+ }
+
+ // no eeprom saved or invalid checksum, load defaults
+ if (!loaded_from_eeprom)
+ {
+ if (type == SB_SUBTYPE_CLONE_AZT2316A_0X11)
+ {
+ read_eeprom[0] = 0x00;
+ read_eeprom[1] = 0x00;
+ read_eeprom[2] = 0x00;
+ read_eeprom[3] = 0x00;
+ read_eeprom[4] = 0x00;
+ read_eeprom[5] = 0x00;
+ read_eeprom[6] = 0x00;
+ read_eeprom[7] = 0x00;
+ read_eeprom[8] = 0x00;
+ read_eeprom[9] = 0x00;
+ read_eeprom[10] = 0x00;
+ read_eeprom[11] = 0x88;
+ read_eeprom[12] = 0xbc;
+ read_eeprom[13] = 0x00;
+ read_eeprom[14] = 0x01;
+ read_eeprom[15] = 0x00;
+ }
+ else if (type == SB_SUBTYPE_CLONE_AZT1605_0X0C)
+ {
+ read_eeprom[0] = 0x80;
+ read_eeprom[1] = 0x80;
+ read_eeprom[2] = 0x9F;
+ read_eeprom[3] = 0x13;
+ read_eeprom[4] = 0x16;
+ read_eeprom[5] = 0x13;
+ read_eeprom[6] = 0x00;
+ read_eeprom[7] = 0x00;
+ read_eeprom[8] = 0x16;
+ read_eeprom[9] = 0x0B;
+ read_eeprom[10] = 0x06;
+ read_eeprom[11] = 0x01;
+ read_eeprom[12] = 0x1C;
+ read_eeprom[13] = 0x14;
+ read_eeprom[14] = 0x04;
+ read_eeprom[15] = 0x1C;
+ }
+ else
+ fatal("Aztech: unknown type %d\n", type);
+ }
+
+ // restore settings from EEPROM bytes
+ if (type == SB_SUBTYPE_CLONE_AZT2316A_0X11)
+ {
+ azt2316a->config_word = read_eeprom[11] + (read_eeprom[12] << 8) + (read_eeprom[13] << 16) + (read_eeprom[14] << 24);
+ switch (azt2316a->config_word & (3 << 0))
+ {
+ case 0:
+ azt2316a->cur_addr = 0x220;
+ break;
+ case 1:
+ azt2316a->cur_addr = 0x240;
+ break;
+ default:
+ fatal("AZT2316A: invalid sb addr in config word %08X\n", azt2316a->config_word);
+ }
+
+ if (azt2316a->config_word & (1 << 2))
+ azt2316a->cur_irq = 2;
+ else if (azt2316a->config_word & (1 << 3))
+ azt2316a->cur_irq = 5;
+ else if (azt2316a->config_word & (1 << 4))
+ azt2316a->cur_irq = 7;
+ else if (azt2316a->config_word & (1 << 5))
+ azt2316a->cur_irq = 10;
+ else
+ fatal("AZT2316A: invalid sb irq in config word %08X\n", azt2316a->config_word);
+
+ switch (azt2316a->config_word & (3 << 6))
+ {
+ case 1 << 6:
+ azt2316a->cur_dma = 0;
+ break;
+ case 2 << 6:
+ azt2316a->cur_dma = 1;
+ break;
+ case 3 << 6:
+ azt2316a->cur_dma = 3;
+ break;
+ default:
+ fatal("AZT2316A: invalid sb dma in config word %08X\n", azt2316a->config_word);
+ }
+
+ switch (azt2316a->config_word & (3 << 8))
+ {
+ case 0:
+ azt2316a->cur_wss_addr = 0x530;
+ break;
+ case 1 << 8:
+ azt2316a->cur_wss_addr = 0x604;
+ break;
+ case 2 << 8:
+ azt2316a->cur_wss_addr = 0xE80;
+ break;
+ case 3 << 8:
+ azt2316a->cur_wss_addr = 0xF40;
+ break;
+ default:
+ fatal("AZT2316A: invalid wss addr in config word %08X\n", azt2316a->config_word);
+ }
+
+ if (azt2316a->config_word & (1 << 10))
+ azt2316a->cur_wss_enabled = 1;
+ else
+ azt2316a->cur_wss_enabled = 0;
+
+ // game_enabled is hardcoded
+ //if (azt2316a->config_word & (1 << 11))
+ // azt2316a->cur_game_enabled = 1;
+ //else
+ // azt2316a->cur_game_enabled = 0;
+
+ if (azt2316a->config_word & (1 << 12))
+ azt2316a->cur_mpu401_addr = 0x330;
+ else
+ azt2316a->cur_mpu401_addr = 0x300;
+
+ // mpu401_enabled is hardcoded
+ //if (azt2316a->config_word & (1 << 13))
+ // azt2316a->cur_mpu401_enabled = 1;
+ //else
+ // azt2316a->cur_mpu401_enabled = 0;
+
+ // cd_addr is hardcoded
+ //switch (azt2316a->config_word & (3 << 14))
+ //{
+ // case 0:
+ // azt2316a->cur_cd_addr = 0x310;
+ // break;
+ // case 1 << 14:
+ // azt2316a->cur_cd_addr = 0x320;
+ // break;
+ // case 2 << 14:
+ // azt2316a->cur_cd_addr = 0x340;
+ // break;
+ // case 3 << 14:
+ // azt2316a->cur_cd_addr = 0x350;
+ // break;
+ // default:
+ // fatal("AZT2316A: invalid cd addr in config word %08X\n", azt2316a->config_word);
+ //}
+
+ // cd_type is hardcoded
+ //azt2316a->cur_cd_type = (azt2316a->config_word >> 16) & 0x7;
+
+ // cd_dma8 is hardcoded
+ //switch (azt2316a->config_word & (3 << 20))
+ //{
+ // case 0:
+ // azt2316a->cur_cd_dma8 = -1;
+ // break;
+ // case 1 << 20:
+ // azt2316a->cur_cd_dma8 = 0;
+ // break;
+ // case 2 << 20:
+ // azt2316a->cur_cd_dma8 = 1;
+ // break;
+ // case 3 << 20:
+ // azt2316a->cur_cd_dma8 = 3;
+ // break;
+ // default:
+ // fatal("AZT2316A: invalid cd dma8 in config word %08X\n", azt2316a->config_word);
+ //}
+
+ // cd_dma16 is hardcoded
+ //switch (azt2316a->config_word & (3 << 22))
+ //{
+ // case 0:
+ // azt2316a->cur_cd_dma16 = -1;
+ // break;
+ // case 1 << 22:
+ // azt2316a->cur_cd_dma16 = 5;
+ // break;
+ // case 2 << 22:
+ // azt2316a->cur_cd_dma16 = 6;
+ // break;
+ // case 3 << 22:
+ // azt2316a->cur_cd_dma16 = 7;
+ // break;
+ // default:
+ // fatal("AZT2316A: invalid cd dma16 in config word %08X\n", azt2316a->config_word);
+ //}
+
+ if (azt2316a->config_word & (1 << 24))
+ azt2316a->cur_mpu401_irq = 2;
+ else if (azt2316a->config_word & (1 << 25))
+ azt2316a->cur_mpu401_irq = 5;
+ else if (azt2316a->config_word & (1 << 26))
+ azt2316a->cur_mpu401_irq = 7;
+ else if (azt2316a->config_word & (1 << 27))
+ azt2316a->cur_mpu401_irq = 10;
+ else
+ fatal("AZT2316A: invalid mpu401 irq in config word %08X\n", azt2316a->config_word);
+
+ // cd_irq is hardcoded
+ //if (azt2316a->config_word & (1 << 28))
+ // azt2316a->cur_cd_irq = 5;
+ //else if (azt2316a->config_word & (1 << 29))
+ // azt2316a->cur_cd_irq = 11;
+ //else if (azt2316a->config_word & (1 << 30))
+ // azt2316a->cur_cd_irq = 12;
+ //else if (azt2316a->config_word & (1 << 31))
+ // azt2316a->cur_cd_irq = 15;
+ //else
+ // fatal("AZT2316A: invalid cd irq in config word %08X\n", azt2316a->config_word);
+
+ // these are not present on the EEPROM
+ azt2316a->cur_wss_irq = 10;
+ azt2316a->cur_wss_dma = 0;
+ azt2316a->cur_mode = 0;
+ }
+ else if (type == SB_SUBTYPE_CLONE_AZT1605_0X0C)
+ {
+ azt2316a->config_word = read_eeprom[12] + (read_eeprom[13] << 8) + (read_eeprom[14] << 16);
+ switch (azt2316a->config_word & (3 << 0))
+ {
+ case 0:
+ azt2316a->cur_addr = 0x220;
+ break;
+ case 1:
+ azt2316a->cur_addr = 0x240;
+ break;
+ default:
+ fatal("AZT1605: invalid sb addr in config word %08X\n", azt2316a->config_word);
+ }
+
+ if (azt2316a->config_word & (1 << 2))
+ azt2316a->cur_mpu401_addr = 0x330;
+ else
+ azt2316a->cur_mpu401_addr = 0x300;
+
+ // mpu401_enabled is hardcoded
+ //if (azt2316a->config_word & (1 << 3))
+ // azt2316a->cur_mpu401_enabled = 1;
+ //else
+ // azt2316a->cur_mpu401_enabled = 0;
+
+ // game_enabled is hardcoded
+ //if (azt2316a->config_word & (1 << 4))
+ // azt2316a->cur_game_enabled = 1;
+ //else
+ // azt2316a->cur_game_enabled = 0;
+
+ // cd_type is hardcoded
+ //azt2316a->cur_cd_type = (azt2316a->config_word >> 5) & 0x7;
+
+ if (azt2316a->config_word & (1 << 8))
+ azt2316a->cur_irq = 2;
+ else if (azt2316a->config_word & (1 << 9))
+ azt2316a->cur_irq = 3;
+ else if (azt2316a->config_word & (1 << 10))
+ azt2316a->cur_irq = 5;
+ else if (azt2316a->config_word & (1 << 11))
+ azt2316a->cur_irq = 7;
+ else
+ fatal("AZT1605: invalid sb irq in config word %08X\n", azt2316a->config_word);
+
+ if (azt2316a->config_word & (1 << 12))
+ azt2316a->cur_mpu401_irq = 2;
+ else if (azt2316a->config_word & (1 << 13))
+ azt2316a->cur_mpu401_irq = 3;
+ else if (azt2316a->config_word & (1 << 14))
+ azt2316a->cur_mpu401_irq = 5;
+ else if (azt2316a->config_word & (1 << 15))
+ azt2316a->cur_mpu401_irq = 7;
+ else
+ fatal("AZT1605: invalid mpu401 irq in config word %08X\n", azt2316a->config_word);
+
+ switch (azt2316a->config_word & (3 << 16))
+ {
+ case 0:
+ azt2316a->cur_wss_addr = 0x530;
+ break;
+ case 1 << 16:
+ azt2316a->cur_wss_addr = 0x604;
+ break;
+ case 2 << 16:
+ azt2316a->cur_wss_addr = 0xE80;
+ break;
+ case 3 << 16:
+ azt2316a->cur_wss_addr = 0xF40;
+ break;
+ default:
+ fatal("AZT1605: invalid wss addr in config word %08X\n", azt2316a->config_word);
+ }
+
+ if (azt2316a->config_word & (1 << 18))
+ azt2316a->cur_wss_enabled = 1;
+ else
+ azt2316a->cur_wss_enabled = 0;
+
+ // cd_irq is hardcoded
+ //if (azt2316a->config_word & (1 << 19))
+ // azt2316a->cur_cd_irq = 11;
+ //else if (azt2316a->config_word & (1 << 20))
+ // azt2316a->cur_cd_irq = 12;
+ //else if (azt2316a->config_word & (1 << 21))
+ // azt2316a->cur_cd_irq = 15;
+ //else
+ // fatal("AZT1605: invalid cd irq in config word %08X\n", azt2316a->config_word);
+
+ // cd_dma8 is hardcoded
+ //switch (azt2316a->config_word & (3 << 22))
+ //{
+ // case 0:
+ // azt2316a->cur_cd_dma8 = -1;
+ // break;
+ // case 1 << 22:
+ // azt2316a->cur_cd_dma8 = 0;
+ // break;
+ // case 2 << 22:
+ // azt2316a->cur_cd_dma8 = 1;
+ // break;
+ // case 3 << 22:
+ // azt2316a->cur_cd_dma8 = 3;
+ // break;
+ // default:
+ // fatal("AZT1605: invalid cd dma8 in config word %08X\n", azt2316a->config_word);
+ //}
+
+ // these are not present on the EEPROM
+ azt2316a->cur_dma = 1; // TODO: investigate TSR to make this work with it - there is no software configurable DMA8?
+ azt2316a->cur_wss_irq = 10;
+ azt2316a->cur_wss_dma = 0;
+ azt2316a->cur_mode = 0;
+ }
+ else
+ fatal("Aztech: unknown type %d\n", type);
+
+ // check for sb addr override jumper
+ addr_setting = device_get_config_int("addr");
+ if (addr_setting)
+ azt2316a->cur_addr = addr_setting;
+
+ // now we can continue initializing
+ azt2316a->opl_emu = device_get_config_int("opl_emu");
+ azt2316a->wss_interrupt_after_config = device_get_config_int("wss_interrupt_after_config");
+
+ azt2316a->type = type;
+
+ // wss part
+ ad1848_init(&azt2316a->ad1848, device_get_config_int("codec"));
+
+ ad1848_setirq(&azt2316a->ad1848, azt2316a->cur_wss_irq);
+ ad1848_setdma(&azt2316a->ad1848, azt2316a->cur_wss_dma);
+
+ io_sethandler(azt2316a->cur_addr + 0x0400, 0x0040, azt2316a_config_read, NULL, NULL, azt2316a_config_write, NULL, NULL, azt2316a);
+ io_sethandler(azt2316a->cur_wss_addr, 0x0004, azt2316a_wss_read, NULL, NULL, azt2316a_wss_write, NULL, NULL, azt2316a);
+ io_sethandler(azt2316a->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &azt2316a->ad1848);
+
+ // sbprov2 part
+ /*sbpro port mappings. 220h or 240h.
+ 2x0 to 2x3 -> FM chip (18 voices)
+ 2x4 to 2x5 -> Mixer interface
+ 2x6, 2xA, 2xC, 2xE -> DSP chip
+
+ 2x8, 2x9, 388 and 389 FM chip (9 voices).*/
+ azt2316a->sb = malloc(sizeof(sb_t));
+ memset(azt2316a->sb, 0, sizeof(sb_t));
+
+ for (i = 0; i < AZTECH_EEPROM_SIZE; i++)
+ azt2316a->sb->dsp.azt_eeprom[i] = read_eeprom[i];
+
+ azt2316a->sb->opl_emu = azt2316a->opl_emu;
+ opl3_init(&azt2316a->sb->opl, azt2316a->sb->opl_emu);
+ sb_dsp_init(&azt2316a->sb->dsp, SBPRO2, azt2316a->type, azt2316a);
+ sb_dsp_setaddr(&azt2316a->sb->dsp, azt2316a->cur_addr);
+ sb_dsp_setirq(&azt2316a->sb->dsp, azt2316a->cur_irq);
+ sb_dsp_setdma8(&azt2316a->sb->dsp, azt2316a->cur_dma);
+ sb_ct1345_mixer_reset(azt2316a->sb);
+ /* DSP I/O handler is activated in sb_dsp_setaddr */
+ io_sethandler(azt2316a->cur_addr+0, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &azt2316a->sb->opl);
+ io_sethandler(azt2316a->cur_addr+8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &azt2316a->sb->opl);
+ io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &azt2316a->sb->opl);
+ io_sethandler(azt2316a->cur_addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, azt2316a->sb);
+ mpu401_uart_init(&azt2316a->sb->mpu, azt2316a->cur_mpu401_addr, azt2316a->cur_mpu401_irq, 1);
+
+ azt2316a_create_config_word(azt2316a); // recreate even if we have read it from EEPROM, because we have some overrides (CD interfaces always off, etc)
+ sound_add_handler(azt2316a_get_buffer, azt2316a);
+
+ return azt2316a;
+}
+
+void *azt2316a_init()
+{
+ return azt_common_init(SB_SUBTYPE_CLONE_AZT2316A_0X11, "azt2316a.nvr");
+}
+
+void *azt1605_init()
+{
+ return azt_common_init(SB_SUBTYPE_CLONE_AZT1605_0X0C, "azt1605.nvr");
+}
+
+void azt_common_close(void *p, char *nvr_filename)
+{
+ azt2316a_t *azt2316a = (azt2316a_t *)p;
+ int i;
+ uint8_t checksum = 0x7F;
+
+ // always save to eeprom (recover from bad values)
+ FILE *f = nvrfopen(nvr_filename, "wb");
+ if (f)
+ {
+ for (i = 0; i < AZTECH_EEPROM_SIZE; i++)
+ checksum += azt2316a->sb->dsp.azt_eeprom[i];
+ fwrite(azt2316a->sb->dsp.azt_eeprom, AZTECH_EEPROM_SIZE, 1, f);
+
+ // TODO: confirm any models saving mixer settings to EEPROM and implement reading back
+ // TODO: should remember to save wss duplex setting if PCem has voice recording implemented in the future? Also, default azt2316a->wss_config
+ // TODO: azt2316a->cur_mode is not saved to EEPROM?
+ fwrite(&checksum, sizeof(checksum), 1, f);
+
+ fclose(f);
+ }
+
+ sb_close(azt2316a->sb);
+
+ free(azt2316a);
+}
+
+void azt2316a_close(void *p)
+{
+ azt_common_close(p, "azt2316a.nvr");
+}
+
+void azt1605_close(void *p)
+{
+ azt_common_close(p, "azt1605.nvr");
+}
+
+void azt2316a_speed_changed(void *p)
+{
+ azt2316a_t *azt2316a = (azt2316a_t *)p;
+
+ ad1848_speed_changed(&azt2316a->ad1848);
+ sb_speed_changed(azt2316a->sb);
+}
+
+void azt2316a_add_status_info(char *s, int max_len, void *p)
+{
+ azt2316a_t *azt2316a = (azt2316a_t *)p;
+
+ sb_dsp_add_status_info(s, max_len, &azt2316a->sb->dsp);
+}
+
+static device_config_t azt2316a_config[] =
+{
+ {
+ .name = "codec",
+ .description = "CODEC",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "CS4248",
+ .value = AD1848_TYPE_CS4248
+ },
+ {
+ .description = "CS4231",
+ .value = AD1848_TYPE_CS4231
+ },
+ },
+ .default_int = AD1848_TYPE_CS4248
+ },
+ {
+ .name = "wss_interrupt_after_config",
+ .description = "Raise CODEC interrupt on CODEC setup (needed by some drivers)",
+ .type = CONFIG_BINARY,
+ .default_int = 0
+ },
+ {
+ .name = "addr",
+ .description = "SB Address",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "0x220",
+ .value = 0x220
+ },
+ {
+ .description = "0x240",
+ .value = 0x240
+ },
+ {
+ .description = "Use EEPROM setting",
+ .value = 0
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 0
+ },
+ {
+ .name = "midi",
+ .description = "MIDI out device",
+ .type = CONFIG_MIDI,
+ .default_int = 0
+ },
+ {
+ .name = "opl_emu",
+ .description = "OPL emulator",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "DBOPL",
+ .value = OPL_DBOPL
+ },
+ {
+ .description = "NukedOPL",
+ .value = OPL_NUKED
+ },
+ },
+ .default_int = OPL_DBOPL
+ },
+ {
+ .type = -1
+ }
+};
+
+device_t azt2316a_device =
+{
+ "Aztech Sound Galaxy Pro 16 AB (Washington)",
+ 0,
+ azt2316a_init,
+ azt2316a_close,
+ NULL,
+ azt2316a_speed_changed,
+ NULL,
+ azt2316a_add_status_info,
+ azt2316a_config
+};
+
+device_t azt1605_device =
+{
+ "Aztech Sound Galaxy Nova 16 Extra (Clinton)",
+ DEVICE_NOT_WORKING,
+ azt1605_init,
+ azt1605_close,
+ NULL,
+ azt2316a_speed_changed,
+ NULL,
+ azt2316a_add_status_info,
+ azt2316a_config
+};
diff --git a/src/sound_azt2316a.h b/src/sound_azt2316a.h
new file mode 100644
index 0000000..2b7d7fa
--- /dev/null
+++ b/src/sound_azt2316a.h
@@ -0,0 +1,4 @@
+extern device_t azt2316a_device;
+extern device_t azt1605_device;
+
+void azt2316a_enable_wss(uint8_t enable, void *p);
diff --git a/src/sound_emu8k.c b/src/sound_emu8k.c
index e283922..bee7e1b 100644
--- a/src/sound_emu8k.c
+++ b/src/sound_emu8k.c
@@ -1719,106 +1719,109 @@ void emu8k_update(emu8k_t *emu8k)
{
int32_t dat;
- /* Waveform oscillator */
-#ifdef RESAMPLER_LINEAR
- dat = EMU8K_READ_INTERP_LINEAR(emu8k, emu_voice->addr.int_address,
- emu_voice->addr.fract_address);
-
-#elif defined RESAMPLER_CUBIC
- dat = EMU8K_READ_INTERP_CUBIC(emu8k, emu_voice->addr.int_address,
- emu_voice->addr.fract_address);
-#endif
-
- /* Filter section */
- if (emu_voice->filterq_idx || emu_voice->cvcf_curr_filt_ctoff != 0xFFFF )
+ if (emu_voice->cvcf_curr_volume)
{
- int cutoff = emu_voice->cvcf_curr_filt_ctoff >> 8;
- const int64_t coef0 = filt_coeffs[emu_voice->filterq_idx][cutoff][0];
- const int64_t coef1 = filt_coeffs[emu_voice->filterq_idx][cutoff][1];
- const int64_t coef2 = filt_coeffs[emu_voice->filterq_idx][cutoff][2];
- /* clip at twice the range */
- #define ClipBuffer(buf) (buf < -16777216) ? -16777216 : (buf > 16777216) ? 16777216 : buf
+ /* Waveform oscillator */
+ #ifdef RESAMPLER_LINEAR
+ dat = EMU8K_READ_INTERP_LINEAR(emu8k, emu_voice->addr.int_address,
+ emu_voice->addr.fract_address);
- #ifdef FILTER_INITIAL
- #define NOOP(x) (void)x;
- NOOP(coef1)
- /* Apply expected attenuation. (FILTER_MOOG does it implicitly, but this one doesn't).
- * Work in 24bits. */
- dat = (dat * emu_voice->filt_att) >> 8;
-
- int64_t vhp = ((-emu_voice->filt_buffer[0] * coef2) >> 24) - emu_voice->filt_buffer[1] - dat;
- emu_voice->filt_buffer[1] += (emu_voice->filt_buffer[0] * coef0) >> 24;
- emu_voice->filt_buffer[0] += (vhp * coef0) >> 24;
- dat = (int32_t)(emu_voice->filt_buffer[1] >> 8);
- if (dat > 32767) { dat = 32767; }
- else if (dat < -32768) { dat = -32768; }
+ #elif defined RESAMPLER_CUBIC
+ dat = EMU8K_READ_INTERP_CUBIC(emu8k, emu_voice->addr.int_address,
+ emu_voice->addr.fract_address);
+ #endif
- #elif defined FILTER_MOOG
-
- /*move to 24bits*/
- dat <<= 8;
-
- dat -= (coef2 * emu_voice->filt_buffer[4]) >> 24; /*feedback*/
- int64_t t1 = emu_voice->filt_buffer[1];
- emu_voice->filt_buffer[1] = ((dat + emu_voice->filt_buffer[0]) * coef0 - emu_voice->filt_buffer[1] * coef1) >> 24;
- emu_voice->filt_buffer[1] = ClipBuffer(emu_voice->filt_buffer[1]);
-
- int64_t t2 = emu_voice->filt_buffer[2];
- emu_voice->filt_buffer[2] = ((emu_voice->filt_buffer[1] + t1) * coef0 - emu_voice->filt_buffer[2] * coef1) >> 24;
- emu_voice->filt_buffer[2] = ClipBuffer(emu_voice->filt_buffer[2]);
-
- int64_t t3 = emu_voice->filt_buffer[3];
- emu_voice->filt_buffer[3] = ((emu_voice->filt_buffer[2] + t2) * coef0 - emu_voice->filt_buffer[3] * coef1) >> 24;
- emu_voice->filt_buffer[3] = ClipBuffer(emu_voice->filt_buffer[3]);
-
- emu_voice->filt_buffer[4] = ((emu_voice->filt_buffer[3] + t3) * coef0 - emu_voice->filt_buffer[4] * coef1) >> 24;
- emu_voice->filt_buffer[4] = ClipBuffer(emu_voice->filt_buffer[4]);
-
- emu_voice->filt_buffer[0] = ClipBuffer(dat);
-
- dat = (int32_t)(emu_voice->filt_buffer[4] >> 8);
- if (dat > 32767) { dat = 32767; }
- else if (dat < -32768) { dat = -32768; }
-
- #elif defined FILTER_CONSTANT
-
- /* Apply expected attenuation. (FILTER_MOOG does it implicitly, but this one is constant gain).
- * Also stay at 24bits.*/
- dat = (dat * emu_voice->filt_att) >> 8;
-
- emu_voice->filt_buffer[0] = (coef1 * emu_voice->filt_buffer[0]
- + coef0 * (dat +
- ((coef2 * (emu_voice->filt_buffer[0] - emu_voice->filt_buffer[1]))>>24))
- ) >> 24;
- emu_voice->filt_buffer[1] = (coef1 * emu_voice->filt_buffer[1]
- + coef0 * emu_voice->filt_buffer[0]) >> 24;
-
- emu_voice->filt_buffer[0] = ClipBuffer(emu_voice->filt_buffer[0]);
- emu_voice->filt_buffer[1] = ClipBuffer(emu_voice->filt_buffer[1]);
-
- dat = (int32_t)(emu_voice->filt_buffer[1] >> 8);
- if (dat > 32767) { dat = 32767; }
- else if (dat < -32768) { dat = -32768; }
-
- #endif
-
- }
- if (( emu8k->hwcf3 & 0x04) && !CCCA_DMA_ACTIVE(emu_voice->ccca))
- {
- /*volume and pan*/
- dat = (dat * emu_voice->cvcf_curr_volume) >> 16;
-
- (*buf++) += (dat * emu_voice->vol_l) >> 8;
- (*buf++) += (dat * emu_voice->vol_r) >> 8;
-
- /* Effects section */
- if (emu_voice->ptrx_revb_send > 0)
+ /* Filter section */
+ if (emu_voice->filterq_idx || emu_voice->cvcf_curr_filt_ctoff != 0xFFFF )
{
- emu8k->reverb_in_buffer[pos]+=(dat*emu_voice->ptrx_revb_send) >> 8;
+ int cutoff = emu_voice->cvcf_curr_filt_ctoff >> 8;
+ const int64_t coef0 = filt_coeffs[emu_voice->filterq_idx][cutoff][0];
+ const int64_t coef1 = filt_coeffs[emu_voice->filterq_idx][cutoff][1];
+ const int64_t coef2 = filt_coeffs[emu_voice->filterq_idx][cutoff][2];
+ /* clip at twice the range */
+ #define ClipBuffer(buf) (buf < -16777216) ? -16777216 : (buf > 16777216) ? 16777216 : buf
+
+ #ifdef FILTER_INITIAL
+ #define NOOP(x) (void)x;
+ NOOP(coef1)
+ /* Apply expected attenuation. (FILTER_MOOG does it implicitly, but this one doesn't).
+ * Work in 24bits. */
+ dat = (dat * emu_voice->filt_att) >> 8;
+
+ int64_t vhp = ((-emu_voice->filt_buffer[0] * coef2) >> 24) - emu_voice->filt_buffer[1] - dat;
+ emu_voice->filt_buffer[1] += (emu_voice->filt_buffer[0] * coef0) >> 24;
+ emu_voice->filt_buffer[0] += (vhp * coef0) >> 24;
+ dat = (int32_t)(emu_voice->filt_buffer[1] >> 8);
+ if (dat > 32767) { dat = 32767; }
+ else if (dat < -32768) { dat = -32768; }
+
+ #elif defined FILTER_MOOG
+
+ /*move to 24bits*/
+ dat <<= 8;
+
+ dat -= (coef2 * emu_voice->filt_buffer[4]) >> 24; /*feedback*/
+ int64_t t1 = emu_voice->filt_buffer[1];
+ emu_voice->filt_buffer[1] = ((dat + emu_voice->filt_buffer[0]) * coef0 - emu_voice->filt_buffer[1] * coef1) >> 24;
+ emu_voice->filt_buffer[1] = ClipBuffer(emu_voice->filt_buffer[1]);
+
+ int64_t t2 = emu_voice->filt_buffer[2];
+ emu_voice->filt_buffer[2] = ((emu_voice->filt_buffer[1] + t1) * coef0 - emu_voice->filt_buffer[2] * coef1) >> 24;
+ emu_voice->filt_buffer[2] = ClipBuffer(emu_voice->filt_buffer[2]);
+
+ int64_t t3 = emu_voice->filt_buffer[3];
+ emu_voice->filt_buffer[3] = ((emu_voice->filt_buffer[2] + t2) * coef0 - emu_voice->filt_buffer[3] * coef1) >> 24;
+ emu_voice->filt_buffer[3] = ClipBuffer(emu_voice->filt_buffer[3]);
+
+ emu_voice->filt_buffer[4] = ((emu_voice->filt_buffer[3] + t3) * coef0 - emu_voice->filt_buffer[4] * coef1) >> 24;
+ emu_voice->filt_buffer[4] = ClipBuffer(emu_voice->filt_buffer[4]);
+
+ emu_voice->filt_buffer[0] = ClipBuffer(dat);
+
+ dat = (int32_t)(emu_voice->filt_buffer[4] >> 8);
+ if (dat > 32767) { dat = 32767; }
+ else if (dat < -32768) { dat = -32768; }
+
+ #elif defined FILTER_CONSTANT
+
+ /* Apply expected attenuation. (FILTER_MOOG does it implicitly, but this one is constant gain).
+ * Also stay at 24bits.*/
+ dat = (dat * emu_voice->filt_att) >> 8;
+
+ emu_voice->filt_buffer[0] = (coef1 * emu_voice->filt_buffer[0]
+ + coef0 * (dat +
+ ((coef2 * (emu_voice->filt_buffer[0] - emu_voice->filt_buffer[1]))>>24))
+ ) >> 24;
+ emu_voice->filt_buffer[1] = (coef1 * emu_voice->filt_buffer[1]
+ + coef0 * emu_voice->filt_buffer[0]) >> 24;
+
+ emu_voice->filt_buffer[0] = ClipBuffer(emu_voice->filt_buffer[0]);
+ emu_voice->filt_buffer[1] = ClipBuffer(emu_voice->filt_buffer[1]);
+
+ dat = (int32_t)(emu_voice->filt_buffer[1] >> 8);
+ if (dat > 32767) { dat = 32767; }
+ else if (dat < -32768) { dat = -32768; }
+
+ #endif
+
}
- if (emu_voice->csl_chor_send > 0)
+ if (( emu8k->hwcf3 & 0x04) && !CCCA_DMA_ACTIVE(emu_voice->ccca))
{
- emu8k->chorus_in_buffer[pos]+=(dat*emu_voice->csl_chor_send) >> 8;
+ /*volume and pan*/
+ dat = (dat * emu_voice->cvcf_curr_volume) >> 16;
+
+ (*buf++) += (dat * emu_voice->vol_l) >> 8;
+ (*buf++) += (dat * emu_voice->vol_r) >> 8;
+
+ /* Effects section */
+ if (emu_voice->ptrx_revb_send > 0)
+ {
+ emu8k->reverb_in_buffer[pos]+=(dat*emu_voice->ptrx_revb_send) >> 8;
+ }
+ if (emu_voice->csl_chor_send > 0)
+ {
+ emu8k->chorus_in_buffer[pos]+=(dat*emu_voice->csl_chor_send) >> 8;
+ }
}
}
diff --git a/src/sound_emu8k.h b/src/sound_emu8k.h
index 4094863..85eeea6 100644
--- a/src/sound_emu8k.h
+++ b/src/sound_emu8k.h
@@ -1,3 +1,5 @@
+#ifndef SOUND_EMU8K_H
+#define SOUND_EMU8K_H
/* All these defines are in samples, not in bytes. */
#define EMU8K_MEM_ADDRESS_MASK 0xFFFFFF
@@ -773,3 +775,5 @@ Treble Parameters:
0xD308 0xD308 0xD308 0xD308 0xD308 0xD308 0xD3019 0xD32A 0xD34C 0xD36E 0xD36E 0xD36E
0x0001 0x0001 0x0001 0x0001 0x0001 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002
*/
+
+#endif /* SOUND_EMU8K_H */
diff --git a/src/sound_gus.c b/src/sound_gus.c
index 20df0c3..05700c2 100644
--- a/src/sound_gus.c
+++ b/src/sound_gus.c
@@ -85,40 +85,6 @@ int gusfreqs[]=
double vol16bit[4096];
-void pollgusirqs(gus_t *gus)
-{
- int c;
-
- gus->irqstatus&=~0x60;
- for (c=0;c<32;c++)
- {
- if (gus->waveirqs[c])
- {
-// gus->waveirqs[c]=0;
- gus->irqstatus2=0x60|c;
- if (gus->rampirqs[c]) gus->irqstatus2 |= 0x80;
- gus->irqstatus|=0x20;
-// printf("Voice IRQ %i %02X %i\n",c,gus->irqstatus2,ins);
- if (gus->irq != -1)
- picint(1 << gus->irq);
- return;
- }
- if (gus->rampirqs[c])
- {
-// gus->rampirqs[c]=0;
- gus->irqstatus2=0xA0|c;
- gus->irqstatus|=0x40;
-// printf("Ramp IRQ %i %02X %i\n",c,gus->irqstatus2,ins);
- if (gus->irq != -1)
- picint(1 << gus->irq);
- return;
- }
- }
- gus->irqstatus2=0xE0;
-// gus->irqstatus&=~0x20;
- if (!gus->irqstatus && gus->irq != -1) picintc(1 << gus->irq);
-}
-
enum
{
MIDI_INT_RECEIVE = 0x01,
@@ -144,6 +110,73 @@ enum
GUS_TIMER_CTRL_AUTO = 0x01
};
+void gus_update_int_status(gus_t *gus)
+{
+ int c;
+ int irq_pending = 0;
+ int midi_irq_pending = 0;
+
+ gus->irqstatus&=~0x60;
+ gus->irqstatus2=0xE0;
+ for (c=0;c<32;c++)
+ {
+ if (gus->waveirqs[c])
+ {
+// gus->waveirqs[c]=0;
+ gus->irqstatus2=0x60|c;
+ if (gus->rampirqs[c]) gus->irqstatus2 |= 0x80;
+ gus->irqstatus|=0x20;
+// printf(" Voice IRQ %i %02X %i\n",c,gus->irqstatus2,ins);
+ irq_pending = 1;
+ break;
+ }
+ if (gus->rampirqs[c])
+ {
+// gus->rampirqs[c]=0;
+ gus->irqstatus2=0xA0|c;
+ gus->irqstatus|=0x40;
+// printf(" Ramp IRQ %i %02X %i\n",c,gus->irqstatus2,ins);
+ irq_pending = 1;
+ break;
+ }
+ }
+ if ((gus->tctrl & 4) && (gus->irqstatus & 0x04))
+ irq_pending = 1; /*Timer 1 interrupt pending*/
+ if ((gus->tctrl & 8) && (gus->irqstatus & 0x08))
+ irq_pending = 1; /*Timer 2 interrupt pending*/
+ if ((gus->irqstatus & 0x80) && (gus->dmactrl & 0x20))
+ irq_pending = 1; /*DMA TC interrupt pending*/
+
+ midi_irq_pending = gus->midi_status & MIDI_INT_MASTER;
+
+// pclog("gus_update_int_status: tctrl=%02x irqstatus=%02x irq_pending=%i midi_irq_pending=%i gus->irq=%i gus->irq_midi=%i\n",
+// gus->tctrl, gus->irqstatus, irq_pending, midi_irq_pending, gus->irq, gus->irq_midi);
+ if (gus->irq == gus->irq_midi && gus->irq != -1)
+ {
+ if (irq_pending || midi_irq_pending)
+ picintlevel(1 << gus->irq);
+ else
+ picintc(1 << gus->irq);
+ }
+ else
+ {
+ if (gus->irq != -1)
+ {
+ if (irq_pending)
+ picintlevel(1 << gus->irq);
+ else
+ picintc(1 << gus->irq);
+ }
+ if (gus->irq_midi != -1)
+ {
+ if (midi_irq_pending)
+ picintlevel(1 << gus->irq_midi);
+ else
+ picintc(1 << gus->irq_midi);
+ }
+ }
+}
+
void gus_midi_update_int_status(gus_t *gus)
{
gus->midi_status &= ~MIDI_INT_MASTER;
@@ -163,11 +196,7 @@ void gus_midi_update_int_status(gus_t *gus)
else
gus->irqstatus &= ~GUS_INT_MIDI_RECEIVE;
- if ((gus->midi_status & MIDI_INT_MASTER) && (gus->irq_midi != -1))
- {
-// pclog("Take MIDI IRQ\n");
- picint(1 << gus->irq_midi);
- }
+ gus_update_int_status(gus);
}
void writegus(uint16_t addr, uint8_t val, void *p)
@@ -271,6 +300,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8);
case 0x45: /*Timer control*/
// printf("Timer control %02X\n",val);
gus->tctrl=val;
+ gus_update_int_status(gus);
break;
}
break;
@@ -291,7 +321,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8);
old = gus->waveirqs[gus->voice];
gus->waveirqs[gus->voice] = ((val & 0xa0) == 0xa0) ? 1 : 0;
if (gus->waveirqs[gus->voice] != old)
- pollgusirqs(gus);
+ gus_update_int_status(gus);
break;
case 1: /*Frequency control*/
gus->freq[gus->voice]=(gus->freq[gus->voice]&0xFF)|(val<<8);
@@ -355,7 +385,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
gus->rctrl[gus->voice] = val & 0x7F;
gus->rampirqs[gus->voice] = ((val & 0xa0) == 0xa0) ? 1 : 0;
if (gus->rampirqs[gus->voice] != old)
- pollgusirqs(gus);
+ gus_update_int_status(gus);
// printf("Ramp control %02i %02X %02X %i\n",gus->voice,val,gus->rampirqs[gus->voice],ins);
break;
@@ -408,7 +438,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
}
// printf("GUS->MEM Transferred %i bytes\n",c);
gus->dmactrl=val&~0x40;
- if (val&0x20) gus->irqnext=1;
+ gus->irqnext = 1;
}
else
{
@@ -440,7 +470,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
}
// printf("MEM->GUS Transferred %i bytes\n",c);
gus->dmactrl=val&~0x40;
- if (val&0x20) gus->irqnext=1;
+ gus->irqnext = 1;
}
// exit(-1);
}
@@ -477,6 +507,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
}*/
gus->tctrl=val;
gus->sb_ctrl = val;
+ gus_update_int_status(gus);
break;
case 0x46: /*Timer 1*/
gus->t1 = gus->t1l = val;
@@ -674,7 +705,7 @@ uint8_t readgus(uint16_t addr, void *p)
// pclog("Read IRQ status - %02X\n",val);
gus->rampirqs[gus->irqstatus2&0x1F]=0;
gus->waveirqs[gus->irqstatus2&0x1F]=0;
- pollgusirqs(gus);
+ gus_update_int_status(gus);
return val;
case 0x00: case 0x01: case 0x02: case 0x03:
@@ -722,7 +753,7 @@ uint8_t readgus(uint16_t addr, void *p)
val=gus->irqstatus2;
gus->rampirqs[gus->irqstatus2&0x1F]=0;
gus->waveirqs[gus->irqstatus2&0x1F]=0;
- pollgusirqs(gus);
+ gus_update_int_status(gus);
// pclog("Read IRQ status - %02X %i %i\n",val, gus->waveirqs[gus->irqstatus2&0x1F], gus->rampirqs[gus->irqstatus2&0x1F]);
return val;
@@ -837,8 +868,6 @@ void gus_poll_timer_1(void *p)
gus->ad_status |= 0x40;
if (gus->tctrl&4)
{
- if (gus->irq != -1)
- picint(1 << gus->irq);
gus->ad_status |= 0x04;
gus->irqstatus |= 0x04;
// pclog("GUS T1 IRQ!\n");
@@ -850,10 +879,9 @@ void gus_poll_timer_1(void *p)
// pclog("Take IRQ\n");
gus->irqnext=0;
gus->irqstatus|=0x80;
- if (gus->irq != -1)
- picint(1 << gus->irq);
}
gus_midi_update_int_status(gus);
+ gus_update_int_status(gus);
}
void gus_poll_timer_2(void *p)
@@ -872,8 +900,6 @@ void gus_poll_timer_2(void *p)
gus->ad_status |= 0x20;
if (gus->tctrl&8)
{
- if (gus->irq != -1)
- picint(1 << gus->irq);
gus->ad_status |= 0x02;
gus->irqstatus |= 0x08;
// pclog("GUS T2 IRQ!\n");
@@ -885,9 +911,8 @@ void gus_poll_timer_2(void *p)
// pclog("Take IRQ\n");
gus->irqnext=0;
gus->irqstatus|=0x80;
- if (gus->irq != -1)
- picint(1 << gus->irq);
}
+ gus_update_int_status(gus);
}
static void gus_update(gus_t *gus)
@@ -1075,7 +1100,7 @@ void gus_poll_wave(void *p)
}
if (update_irqs)
- pollgusirqs(gus);
+ gus_update_int_status(gus);
}
static void gus_get_buffer(int32_t *buffer, int len, void *p)
@@ -1156,6 +1181,16 @@ void gus_speed_changed(void *p)
gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14]));
}
+static void gus_add_status_info(char *s, int max_len, void *p)
+{
+ gus_t *gus = (gus_t *)p;
+ char temps[256];
+
+ sprintf(temps, "GUS max voices : %i\nGUS playback frequency : %iHz\n\n",
+ gus->voices, gusfreqs[gus->voices-14]);
+ strncat(s, temps, max_len);
+}
+
device_t gus_device =
{
"Gravis UltraSound",
@@ -1165,5 +1200,5 @@ device_t gus_device =
NULL,
gus_speed_changed,
NULL,
- NULL
+ gus_add_status_info
};
diff --git a/src/sound_mpu401_uart.c b/src/sound_mpu401_uart.c
index b75cfa8..22cb638 100644
--- a/src/sound_mpu401_uart.c
+++ b/src/sound_mpu401_uart.c
@@ -1,5 +1,6 @@
#include "ibm.h"
#include "io.h"
+#include "pic.h"
#include "plat-midi.h"
#include "sound_mpu401_uart.h"
@@ -9,6 +10,14 @@ enum
STATUS_INPUT_NOT_READY = 0x80
};
+static void mpu401_uart_raise_irq(void *p)
+{
+ mpu401_uart_t *mpu = (mpu401_uart_t *)p;
+
+ if (mpu->irq != -1)
+ picint(1 << mpu->irq);
+}
+
static void mpu401_uart_write(uint16_t addr, uint8_t val, void *p)
{
mpu401_uart_t *mpu = (mpu401_uart_t *)p;
@@ -18,15 +27,30 @@ static void mpu401_uart_write(uint16_t addr, uint8_t val, void *p)
switch (val)
{
case 0xff: /*Reset*/
+ // From Roland: "An ACK will not be sent back upon sending a SYSTEM RESET to leave the UART MODE ($3F)."
+ // But actual behaviour is weird. For example, the MPU401 port test in the AZT1605 drivers for Windows NT
+ // want this to return an Ack but the IRQ test in the same driver wants this to raise no interrupts!
mpu->rx_data = 0xfe; /*Acknowledge*/
- mpu->status = 0;
mpu->uart_mode = 0;
+ if (mpu->is_aztech)
+ mpu->status = STATUS_OUTPUT_NOT_READY;
+ else
+ {
+ mpu->status = 0;
+ mpu401_uart_raise_irq(p);
+ }
break;
case 0x3f: /*Enter UART mode*/
mpu->rx_data = 0xfe; /*Acknowledge*/
- mpu->status = 0;
mpu->uart_mode = 1;
+ if (mpu->is_aztech)
+ {
+ mpu->status = STATUS_OUTPUT_NOT_READY;
+ mpu401_uart_raise_irq(p);
+ }
+ else
+ mpu->status = 0;
break;
}
return;
@@ -45,14 +69,31 @@ static uint8_t mpu401_uart_read(uint16_t addr, void *p)
return mpu->status;
/*Data*/
- mpu->status |= STATUS_INPUT_NOT_READY;
+ mpu->status = STATUS_INPUT_NOT_READY;
return mpu->rx_data;
}
-void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr)
+void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr, int irq, int is_aztech)
{
mpu->status = STATUS_INPUT_NOT_READY;
mpu->uart_mode = 0;
+ mpu->addr = addr;
+ mpu->irq = irq;
+ mpu->is_aztech = is_aztech;
io_sethandler(addr, 0x0002, mpu401_uart_read, NULL, NULL, mpu401_uart_write, NULL, NULL, mpu);
}
+
+void mpu401_uart_update_addr(mpu401_uart_t *mpu, uint16_t addr)
+{
+ io_removehandler(mpu->addr, 0x0002, mpu401_uart_read, NULL, NULL, mpu401_uart_write, NULL, NULL, mpu);
+ mpu->addr = addr;
+ if (addr != 0)
+ io_sethandler(addr, 0x0002, mpu401_uart_read, NULL, NULL, mpu401_uart_write, NULL, NULL, mpu);
+}
+
+void mpu401_uart_update_irq(mpu401_uart_t *mpu, int irq)
+{
+ mpu->irq = irq;
+}
+
diff --git a/src/sound_mpu401_uart.h b/src/sound_mpu401_uart.h
index 91f4119..9634d58 100644
--- a/src/sound_mpu401_uart.h
+++ b/src/sound_mpu401_uart.h
@@ -1,9 +1,20 @@
+#ifndef SOUND_MPU401_UART
+#define SOUND_MPU401_UART
+
typedef struct mpu401_uart_t
{
uint8_t status;
uint8_t rx_data;
- int uart_mode;
+ int uart_mode;
+ uint16_t addr;
+ int irq;
+
+ int is_aztech;
} mpu401_uart_t;
-void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr);
+void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr, int irq, int is_aztech);
+void mpu401_uart_update_addr(mpu401_uart_t *mpu, uint16_t addr);
+void mpu401_uart_update_irq(mpu401_uart_t *mpu, int irq);
+
+#endif /* SOUND_MPU401_UART */
diff --git a/src/sound_pas16.c b/src/sound_pas16.c
index d55b921..e88ec2e 100644
--- a/src/sound_pas16.c
+++ b/src/sound_pas16.c
@@ -737,7 +737,7 @@ void *pas16_init()
memset(pas16, 0, sizeof(pas16_t));
opl3_init(&pas16->opl, 0);
- sb_dsp_init(&pas16->dsp, SB2);
+ sb_dsp_init(&pas16->dsp, SB2, SB_SUBTYPE_DEFAULT, pas16);
io_sethandler(0x9a01, 0x0001, NULL, NULL, NULL, pas16_out_base, NULL, NULL, pas16);
diff --git a/src/sound_sb.c b/src/sound_sb.c
index 0fb5d48..08830d0 100644
--- a/src/sound_sb.c
+++ b/src/sound_sb.c
@@ -21,102 +21,6 @@ FILE* soundfsb = 0/*NULL*/;
FILE* soundfsbin = 0/*NULL*/;
#endif
-
-
-/* SB 2.0 CD version */
-typedef struct sb_ct1335_mixer_t
-{
- int32_t master;
- int32_t voice;
- int32_t fm;
- int32_t cd;
-
- uint8_t index;
- uint8_t regs[256];
-} sb_ct1335_mixer_t;
-/* SB PRO */
-typedef struct sb_ct1345_mixer_t
-{
- int32_t master_l, master_r;
- int32_t voice_l, voice_r;
- int32_t fm_l, fm_r;
- int32_t cd_l, cd_r;
- int32_t line_l, line_r;
- int32_t mic;
- /*see sb_ct1745_mixer for values for input selector*/
- int32_t input_selector;
-
- int input_filter;
- int in_filter_freq;
- int output_filter;
-
- int stereo;
- int stereo_isleft;
-
- uint8_t index;
- uint8_t regs[256];
-
-} sb_ct1345_mixer_t;
-/* SB16 and AWE32 */
-typedef struct sb_ct1745_mixer_t
-{
- int32_t master_l, master_r;
- int32_t voice_l, voice_r;
- int32_t fm_l, fm_r;
- int32_t cd_l, cd_r;
- int32_t line_l, line_r;
- int32_t mic;
- int32_t speaker;
-
- int bass_l, bass_r;
- int treble_l, treble_r;
-
- int output_selector;
- #define OUTPUT_MIC 1
- #define OUTPUT_CD_R 2
- #define OUTPUT_CD_L 4
- #define OUTPUT_LINE_R 8
- #define OUTPUT_LINE_L 16
-
- int input_selector_left;
- int input_selector_right;
- #define INPUT_MIC 1
- #define INPUT_CD_R 2
- #define INPUT_CD_L 4
- #define INPUT_LINE_R 8
- #define INPUT_LINE_L 16
- #define INPUT_MIDI_R 32
- #define INPUT_MIDI_L 64
-
- int mic_agc;
-
- int32_t input_gain_L;
- int32_t input_gain_R;
- int32_t output_gain_L;
- int32_t output_gain_R;
-
- uint8_t index;
- uint8_t regs[256];
-} sb_ct1745_mixer_t;
-
-typedef struct sb_t
-{
- opl_t opl;
- sb_dsp_t dsp;
- union {
- sb_ct1335_mixer_t mixer_sb2;
- sb_ct1345_mixer_t mixer_sbpro;
- sb_ct1745_mixer_t mixer_sb16;
- };
- mpu401_uart_t mpu;
- emu8k_t emu8k;
-
- int pos;
-
- uint8_t pos_regs[8];
-
- int opl_emu;
-} sb_t;
/* 0 to 7 -> -14dB to 0dB i 2dB steps. 8 to 15 -> 0 to +14dB in 2dB steps.
Note that for positive dB values, this is not amplitude, it is amplitude-1. */
const float sb_bass_treble_4bits[]= {
@@ -195,7 +99,7 @@ static void sb_get_buffer_sb2_mixer(int32_t *buffer, int len, void *p)
sb->dsp.pos = 0;
}
-static void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p)
+void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p)
{
sb_t *sb = (sb_t *)p;
sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro;
@@ -521,7 +425,7 @@ void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p)
{
/* Compatibility: chain registers 0x02 and 0x22 as well as 0x06 and 0x26 */
case 0x02: case 0x06:
- mixer->regs[mixer->index+0x20]=((val&0xE) << 4)||(val&0xE) << 4;
+ mixer->regs[mixer->index+0x20]=((val&0xE) << 4) | (val&0xE);
break;
case 0x22: case 0x26:
@@ -950,7 +854,7 @@ void *sb_1_init()
memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl);
- sb_dsp_init(&sb->dsp, SB1);
+ sb_dsp_init(&sb->dsp, SB1, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -972,7 +876,7 @@ void *sb_15_init()
memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl);
- sb_dsp_init(&sb->dsp, SB15);
+ sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -993,13 +897,13 @@ void *sb_mcv_init()
memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl);
- sb_dsp_init(&sb->dsp, SB15);
+ sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, 0);//addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
sound_add_handler(sb_get_buffer_sb2, sb);
/* I/O handlers activated in sb_mcv_write */
- mca_add(sb_mcv_read, sb_mcv_write, sb);
+ mca_add(sb_mcv_read, sb_mcv_write, NULL, sb);
sb->pos_regs[0] = 0x84;
sb->pos_regs[1] = 0x50;
return sb;
@@ -1024,7 +928,7 @@ void *sb_2_init()
memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl);
- sb_dsp_init(&sb->dsp, SB2);
+ sb_dsp_init(&sb->dsp, SB2, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -1061,7 +965,7 @@ void *sb_pro_v1_init()
memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl);
- sb_dsp_init(&sb->dsp, SBPRO);
+ sb_dsp_init(&sb->dsp, SBPRO, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -1091,7 +995,7 @@ void *sb_pro_v2_init()
uint16_t addr = device_get_config_int("addr");
sb->opl_emu = device_get_config_int("opl_emu");
opl3_init(&sb->opl, sb->opl_emu);
- sb_dsp_init(&sb->dsp, SBPRO2);
+ sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -1118,13 +1022,13 @@ void *sb_pro_mcv_init()
sb->opl_emu = device_get_config_int("opl_emu");
opl3_init(&sb->opl, sb->opl_emu);
- sb_dsp_init(&sb->dsp, SBPRO2);
+ sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb);
sb_ct1345_mixer_reset(sb);
/* I/O handlers activated in sb_mcv_write */
sound_add_handler(sb_get_buffer_sbpro, sb);
/* I/O handlers activated in sb_pro_mcv_write */
- mca_add(sb_pro_mcv_read, sb_pro_mcv_write, sb);
+ mca_add(sb_pro_mcv_read, sb_pro_mcv_write, NULL, sb);
sb->pos_regs[0] = 0x03;
sb->pos_regs[1] = 0x51;
@@ -1139,7 +1043,7 @@ void *sb_16_init()
uint16_t addr = device_get_config_int("addr");
sb->opl_emu = device_get_config_int("opl_emu");
opl3_init(&sb->opl, sb->opl_emu);
- sb_dsp_init(&sb->dsp, SB16);
+ sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
// TODO: irq and dma options too?
sb_ct1745_mixer_reset(sb);
@@ -1148,7 +1052,7 @@ void *sb_16_init()
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl);
io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb);
sound_add_handler(sb_get_buffer_sb16, sb);
- mpu401_uart_init(&sb->mpu, 0x330);
+ mpu401_uart_init(&sb->mpu, 0x330, -1, 0);
return sb;
@@ -1169,7 +1073,7 @@ void *sb_awe32_init()
uint16_t emu_addr = device_get_config_int("emu_addr");
sb->opl_emu = device_get_config_int("opl_emu");
opl3_init(&sb->opl, sb->opl_emu);
- sb_dsp_init(&sb->dsp, SB16 + 1);
+ sb_dsp_init(&sb->dsp, SB16 + 1, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
// TODO: irq and dma options too?
sb_ct1745_mixer_reset(sb);
@@ -1178,7 +1082,7 @@ void *sb_awe32_init()
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl);
io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb);
sound_add_handler(sb_get_buffer_emu8k, sb);
- mpu401_uart_init(&sb->mpu, 0x330);
+ mpu401_uart_init(&sb->mpu, 0x330, -1, 0);
emu8k_init(&sb->emu8k, emu_addr, onboard_ram);
return sb;
diff --git a/src/sound_sb.h b/src/sound_sb.h
index fb856c8..405bd39 100644
--- a/src/sound_sb.h
+++ b/src/sound_sb.h
@@ -1,3 +1,10 @@
+#ifndef SOUND_SB_H
+#define SOUND_SB_H
+
+#include "sound_emu8k.h"
+#include "sound_mpu401_uart.h"
+#include "sound_sb_dsp.h"
+
extern device_t sb_1_device;
extern device_t sb_15_device;
extern device_t sb_mcv_device;
@@ -7,3 +14,110 @@ extern device_t sb_pro_v2_device;
extern device_t sb_pro_mcv_device;
extern device_t sb_16_device;
extern device_t sb_awe32_device;
+
+/* SB 2.0 CD version */
+typedef struct sb_ct1335_mixer_t
+{
+ int32_t master;
+ int32_t voice;
+ int32_t fm;
+ int32_t cd;
+
+ uint8_t index;
+ uint8_t regs[256];
+} sb_ct1335_mixer_t;
+/* SB PRO */
+typedef struct sb_ct1345_mixer_t
+{
+ int32_t master_l, master_r;
+ int32_t voice_l, voice_r;
+ int32_t fm_l, fm_r;
+ int32_t cd_l, cd_r;
+ int32_t line_l, line_r;
+ int32_t mic;
+ /*see sb_ct1745_mixer for values for input selector*/
+ int32_t input_selector;
+
+ int input_filter;
+ int in_filter_freq;
+ int output_filter;
+
+ int stereo;
+ int stereo_isleft;
+
+ uint8_t index;
+ uint8_t regs[256];
+
+} sb_ct1345_mixer_t;
+/* SB16 and AWE32 */
+typedef struct sb_ct1745_mixer_t
+{
+ int32_t master_l, master_r;
+ int32_t voice_l, voice_r;
+ int32_t fm_l, fm_r;
+ int32_t cd_l, cd_r;
+ int32_t line_l, line_r;
+ int32_t mic;
+ int32_t speaker;
+
+ int bass_l, bass_r;
+ int treble_l, treble_r;
+
+ int output_selector;
+ #define OUTPUT_MIC 1
+ #define OUTPUT_CD_R 2
+ #define OUTPUT_CD_L 4
+ #define OUTPUT_LINE_R 8
+ #define OUTPUT_LINE_L 16
+
+ int input_selector_left;
+ int input_selector_right;
+ #define INPUT_MIC 1
+ #define INPUT_CD_R 2
+ #define INPUT_CD_L 4
+ #define INPUT_LINE_R 8
+ #define INPUT_LINE_L 16
+ #define INPUT_MIDI_R 32
+ #define INPUT_MIDI_L 64
+
+ int mic_agc;
+
+ int32_t input_gain_L;
+ int32_t input_gain_R;
+ int32_t output_gain_L;
+ int32_t output_gain_R;
+
+ uint8_t index;
+ uint8_t regs[256];
+} sb_ct1745_mixer_t;
+
+typedef struct sb_t
+{
+ opl_t opl;
+ sb_dsp_t dsp;
+ union {
+ sb_ct1335_mixer_t mixer_sb2;
+ sb_ct1345_mixer_t mixer_sbpro;
+ sb_ct1745_mixer_t mixer_sb16;
+ };
+ mpu401_uart_t mpu;
+ emu8k_t emu8k;
+
+ int pos;
+
+ uint8_t pos_regs[8];
+
+ int opl_emu;
+} sb_t;
+
+// exported for clone cards
+void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p);
+void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p);
+uint8_t sb_ct1345_mixer_read(uint16_t addr, void *p);
+void sb_ct1345_mixer_reset(sb_t* sb);
+
+void sb_close(void *p);
+void sb_speed_changed(void *p);
+void sb_add_status_info(char *s, int max_len, void *p);
+
+#endif /* SOUND_SB_H */
diff --git a/src/sound_sb_dsp.c b/src/sound_sb_dsp.c
index 25de3ee..3edf0d6 100644
--- a/src/sound_sb_dsp.c
+++ b/src/sound_sb_dsp.c
@@ -10,13 +10,16 @@
#include "ibm.h"
+#include "device.h"
#include "dma.h"
#include "filters.h"
#include "io.h"
#include "pic.h"
#include "sound.h"
+#include "sound_azt2316a.h"
#include "sound_sb_dsp.h"
#include "timer.h"
+#include "x86.h"
/*The recording safety margin is intended for uneven "len" calls to the get_buffer mixer calls on sound_sb*/
#define SB_DSP_REC_SAFEFTY_MARGIN 4096
@@ -205,10 +208,18 @@ void sb_doreset(sb_dsp_t *dsp)
int c;
sb_dsp_reset(dsp);
-
- if (dsp->sb_type==SB16) sb_commands[8] = 1;
- else sb_commands[8] = -1;
-
+
+ if (IS_AZTECH(dsp))
+ {
+ sb_commands[8] = 1;
+ sb_commands[9] = 1;
+ }
+ else
+ {
+ if (dsp->sb_type==SB16) sb_commands[8] = 1;
+ else sb_commands[8] = -1;
+ }
+
for (c = 0; c < 256; c++)
dsp->sb_asp_regs[c] = 0;
dsp->sb_asp_regs[5] = 0x01;
@@ -579,6 +590,20 @@ void sb_exec_command(sb_dsp_t *dsp)
sb_add_data(dsp, ~dsp->sb_data[0]);
break;
case 0xE1: /*Get DSP version*/
+ if (IS_AZTECH(dsp))
+ {
+ if (dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11)
+ {
+ sb_add_data(dsp, 0x3);
+ sb_add_data(dsp, 0x1);
+ }
+ else if (dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C)
+ {
+ sb_add_data(dsp, 0x2);
+ sb_add_data(dsp, 0x1);
+ }
+ break;
+ }
sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] >> 8);
sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] & 0xff);
break;
@@ -617,6 +642,32 @@ void sb_exec_command(sb_dsp_t *dsp)
case 0xFF:
break;
case 0x08: /*ASP get version*/
+ if (IS_AZTECH(dsp))
+ {
+ if ((dsp->sb_data[0] == 0x55 || dsp->sb_data[0] == 0x05) && dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11)
+ sb_add_data(dsp, 0x11); /* AZTECH get type, WASHINGTON/latest - according to devkit. E.g.: The one in the Itautec Infoway Multimidia */
+ else if ((dsp->sb_data[0] == 0x55 || dsp->sb_data[0] == 0x05) && dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C)
+ sb_add_data(dsp, 0x0C); /* AZTECH get type, CLINTON - according to devkit. E.g.: The one in the Packard Bell Legend 100CD */
+ else if (dsp->sb_data[0] == 0x08)
+ {
+ // EEPROM address to write followed by byte
+ if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE)
+ fatal("AZT EEPROM: out of bounds write to %02X\n", dsp->sb_data[1]);
+ dsp->azt_eeprom[dsp->sb_data[1]] = dsp->sb_data[2];
+ break;
+ }
+ else if (dsp->sb_data[0] == 0x07)
+ {
+ // EEPROM address to read
+ if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE)
+ fatal("AZT EEPROM: out of bounds read to %02X\n", dsp->sb_data[1]);
+ sb_add_data(dsp, dsp->azt_eeprom[dsp->sb_data[1]]);
+ break;
+ }
+ else
+ pclog("AZT2316A: UNKNOWN 0x08 COMMAND: %02X\n", dsp->sb_data[0]); // 0x08 (when shutting down, driver tries to read 1 byte of response), 0x55, 0x0D, 0x08D seen
+ break;
+ }
if (dsp->sb_type < SB16) break;
sb_add_data(dsp, 0x18);
break;
@@ -644,10 +695,29 @@ void sb_exec_command(sb_dsp_t *dsp)
case 0x04:
case 0x05:
break;
+ case 0x09: /*AZTECH mode set*/
+ if (IS_AZTECH(dsp))
+ {
+ if (dsp->sb_data[0] == 0x00)
+ {
+ pclog("AZT2316A: WSS MODE!\n");
+ azt2316a_enable_wss(1, dsp->parent);
+ }
+ else if (dsp->sb_data[0] == 0x01)
+ {
+ pclog("AZT2316A: SB8PROV2 MODE!\n");
+ azt2316a_enable_wss(0, dsp->parent);
+ }
+ else
+ pclog("AZT2316A: UNKNOWN MODE!\n"); // sequences 0x02->0xFF, 0x04->0xFF seen
+ }
+ break;
+ case 0x38: /*TODO: AZTECH MIDI-related? */
+ break;
// default:
-// fatal("Exec bad SB command %02X\n",sb_command);
-
-
+// fatal("Exec bad SB command %02X\n",dsp->sb_command);
+
+
/*TODO: Some more data about the DSP registeres
* http://the.earth.li/~tfm/oldpage/sb_dsp.html
* http://www.synchrondata.com/pheaven/www/area19.htm
@@ -680,7 +750,7 @@ void sb_write(uint16_t a, uint8_t v, void *priv)
dsp->sbreset = v;
return;
case 0xC: /*Command/data write*/
- timer_set_delay_u64(&dsp->wb_timer, TIMER_USEC * 1);
+ timer_set_delay_u64(&dsp->wb_timer, TIMER_USEC * 1);
if (dsp->asp_data_len)
{
// pclog("ASP data %i\n", dsp->asp_data_len);
@@ -699,11 +769,27 @@ void sb_write(uint16_t a, uint8_t v, void *priv)
dsp->sb_data_stat++;
}
else
- dsp->sb_data[dsp->sb_data_stat++] = v;
+ {
+ dsp->sb_data[dsp->sb_data_stat++] = v;
+ if (IS_AZTECH(dsp))
+ {
+ // variable length commands
+ if (dsp->sb_command == 0x08 && dsp->sb_data_stat == 1 && dsp->sb_data[0] == 0x08)
+ sb_commands[dsp->sb_command] = 3;
+ else if (dsp->sb_command == 0x08 && dsp->sb_data_stat == 1 && dsp->sb_data[0] == 0x07)
+ sb_commands[dsp->sb_command] = 2;
+ }
+ }
if (dsp->sb_data_stat == sb_commands[dsp->sb_command] || sb_commands[dsp->sb_command] == -1)
{
sb_exec_command(dsp);
dsp->sb_data_stat = -1;
+ if (IS_AZTECH(dsp))
+ {
+ // variable length commands
+ if (dsp->sb_command == 0x08)
+ sb_commands[dsp->sb_command] = 1;
+ }
}
break;
}
@@ -732,13 +818,31 @@ uint8_t sb_read(uint16_t a, void *priv)
if (dsp->wb_full || (dsp->busy_count & 2))
{
dsp->wb_full = timer_is_enabled(&dsp->wb_timer);
- return 0xff;
+// pclog("SB read 0x80\n");
+ if (IS_AZTECH(dsp))
+ return 0x80;
+ else
+ return 0xFF;
}
- return 0x7f;
+// pclog("SB read 0x00\n");
+ if (IS_AZTECH(dsp))
+ return 0x00;
+ else
+ return 0x7F;
case 0xE: /*Read data ready*/
picintc(1 << dsp->sb_irqnum);
dsp->sb_irq8 = dsp->sb_irq16 = 0;
- return (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff;
+ // Only bit 7 is defined but aztech diagnostics fail if the others are set. Keep the original behavior to not interfere with what's already working.
+ if (IS_AZTECH(dsp))
+ {
+// pclog("SB read %02X\n",(dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80);
+ return (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80;
+ }
+ else
+ {
+// pclog("SB read %02X\n",(dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7F : 0xFF);
+ return (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7F : 0xFF;
+ }
case 0xF: /*16-bit ack*/
dsp->sb_irq16 = 0;
if (!dsp->sb_irq8) picintc(1 << dsp->sb_irqnum);
@@ -751,9 +855,11 @@ static void sb_wb_clear(void *p)
{
}
-void sb_dsp_init(sb_dsp_t *dsp, int type)
+void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent)
{
dsp->sb_type = type;
+ dsp->sb_subtype = subtype;
+ dsp->parent = parent;
// Default values. Use sb_dsp_setxxx() methods to change.
dsp->sb_irqnum = 7;
@@ -1279,4 +1385,5 @@ void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp)
sprintf(temps, "SB playback frequency : %iHz\n", freq);
strncat(s, temps, max_len);
}
+ strncat(s, "\n", max_len);
}
diff --git a/src/sound_sb_dsp.h b/src/sound_sb_dsp.h
index cb14af5..33661c0 100644
--- a/src/sound_sb_dsp.h
+++ b/src/sound_sb_dsp.h
@@ -1,6 +1,20 @@
+#ifndef SOUND_SB_DSP_H
+#define SOUND_SB_DSP_H
+
+/*Sound Blaster Clones, for quirks*/
+#define SB_SUBTYPE_DEFAULT 0 /*Handle as a Creative card*/
+#define SB_SUBTYPE_CLONE_AZT2316A_0X11 1 /*Aztech Sound Galaxy Pro 16 AB, DSP 3.1 - SBPRO2 clone*/
+#define SB_SUBTYPE_CLONE_AZT1605_0X0C 2 /*Aztech Sound Galaxy Nova 16 Extra / Packard Bell Forte 16, DSP 2.1 - SBPRO2 clone*/
+
+// aztech-related
+#define IS_AZTECH(dsp) ((dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11 || (dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) // check for future AZT cards here
+#define AZTECH_EEPROM_SIZE 16
+
typedef struct sb_dsp_t
{
int sb_type;
+ int sb_subtype; // which clone
+ void *parent; // "sb_t *" if default subtype, "azt2316a_t *" if aztech.
int sb_8_length, sb_8_format, sb_8_autoinit, sb_8_pause, sb_8_enable, sb_8_autolen, sb_8_output;
int sb_8_dmanum;
@@ -67,9 +81,11 @@ typedef struct sb_dsp_t
int16_t record_buffer[0xFFFF];
int16_t buffer[MAXSOUNDBUFLEN * 2];
int pos;
+
+ uint8_t azt_eeprom[AZTECH_EEPROM_SIZE]; // the eeprom in the Aztech cards is attached to the DSP
} sb_dsp_t;
-void sb_dsp_init(sb_dsp_t *dsp, int type);
+void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent);
void sb_dsp_close(sb_dsp_t *dsp);
void sb_dsp_setirq(sb_dsp_t *dsp, int irq);
@@ -86,3 +102,5 @@ void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo);
void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp);
void sb_dsp_update(sb_dsp_t *dsp);
+
+#endif /* SOUND_SB_DSP_H */
diff --git a/src/sound_wss.c b/src/sound_wss.c
index 4129744..edbc272 100644
--- a/src/sound_wss.c
+++ b/src/sound_wss.c
@@ -84,7 +84,7 @@ void *wss_init()
opl_emu = device_get_config_int("opl_emu");
opl3_init(&wss->opl, opl_emu);
- ad1848_init(&wss->ad1848);
+ ad1848_init(&wss->ad1848, AD1848_TYPE_DEFAULT);
ad1848_setirq(&wss->ad1848, 7);
ad1848_setdma(&wss->ad1848, 3);
diff --git a/src/sst39sf010.c b/src/sst39sf010.c
index 8acb664..b2283f1 100644
--- a/src/sst39sf010.c
+++ b/src/sst39sf010.c
@@ -3,6 +3,7 @@
#include "device.h"
#include "mem.h"
#include "sst39sf010.h"
+#include "xi8088.h"
typedef struct sst_t
{
@@ -25,6 +26,18 @@ typedef struct sst_t
static void set_id_mode(sst_t *sst);
static void clear_id_mode(sst_t *sst);
+static uint32_t sst_masked_rom_addr(uint32_t addr)
+{
+ // The flipped MSB of the Xi 8088 is only present in the on-disk files,
+ // in ram the mapping is as the software sees. This does not cause
+ // problems with the programming commands because they only use the
+ // lower 2 bytes.
+ if (romset == ROM_XI8088 && !xi8088_bios_128kb())
+ return addr & 0xffff;
+ else
+ return addr & 0x1ffff;
+}
+
static void sst_new_command(sst_t *sst, uint8_t val)
{
switch (val)
@@ -69,11 +82,11 @@ static void sst_new_command(sst_t *sst, uint8_t val)
}
}
-static void sst_sector_erase(sst_t *sst, uint32_t addr)
+static void sst_sector_erase(sst_t *sst, uint32_t sst_addr)
{
-// pclog("SST sector erase %08x\n", addr);
- memset(&rom[addr & 0x1f000], 0xff, 4096);
- memset(&sst->data[addr & 0x1f000], 0xff, 4096);
+// pclog("SST sector erase sst_addr %08x\n", sst_addr);
+ memset(&rom[sst_addr & 0x1f000], 0xff, 4096);
+ memset(&sst->data[sst_addr & 0x1f000], 0xff, 4096);
sst->dirty = 1;
}
@@ -117,7 +130,7 @@ static void sst_write(uint32_t addr, uint8_t val, void *p)
sst_new_command(sst, val);
else if (val == SST_SECTOR_ERASE && sst->erase)
{
- sst_sector_erase(sst, addr);
+ sst_sector_erase(sst, sst_masked_rom_addr(addr));
sst->command_state = 0;
}
else
@@ -125,8 +138,8 @@ static void sst_write(uint32_t addr, uint8_t val, void *p)
break;
case 3:
// pclog("Byte program %08x %02x\n", addr, val);
- rom[addr & 0x1ffff] = val;
- sst->data[addr & 0x1ffff] = val;
+ rom[sst_masked_rom_addr(addr)] = val;
+ sst->data[sst_masked_rom_addr(addr)] = val;
sst->command_state = 0;
sst->dirty = 1;
break;
@@ -177,9 +190,14 @@ static void *sst_39sf010_init()
switch(romset)
{
+ case ROM_XI8088:
+ strcpy(sst->flash_path, "xi8088/");
+ break;
+
case ROM_FIC_VA503P:
strcpy(sst->flash_path, "fic_va503p/");
break;
+
default:
fatal("sst_39sf010_init on unsupported ROM set %i\n", romset);
}
@@ -187,7 +205,21 @@ static void *sst_39sf010_init()
f = romfopen(sst->flash_path, "rb");
if (f)
{
- fread(rom, 0x20000, 1, f);
+ switch(romset)
+ {
+ case ROM_XI8088:
+ if (xi8088_bios_128kb())
+ fread(rom + 0x10000, 0x10000, 1, f);
+ fread(rom, 0x10000, 1, f);
+ break;
+
+ case ROM_FIC_VA503P:
+ fread(rom, 0x20000, 1, f);
+ break;
+
+ default:
+ fatal("sst_39sf010_init on unsupported ROM set %i\n", romset);
+ }
fclose(f);
}
memcpy(sst->data, rom, 0x20000);
@@ -204,7 +236,21 @@ static void sst_39sf010_close(void *p)
if (sst->dirty)
{
FILE *f = romfopen(sst->flash_path, "wb");
- fwrite(sst->data, 0x20000, 1, f);
+ switch(romset)
+ {
+ case ROM_XI8088:
+ if (xi8088_bios_128kb())
+ fwrite(sst->data + 0x10000, 0x10000, 1, f);
+ fwrite(sst->data, 0x10000, 1, f);
+ break;
+
+ case ROM_FIC_VA503P:
+ fwrite(sst->data, 0x20000, 1, f);
+ break;
+
+ default:
+ fatal("sst_39sf010_init on unsupported ROM set %i\n", romset);
+ }
fclose(f);
}
diff --git a/src/superxt.c b/src/superxt.c
new file mode 100644
index 0000000..5c3bed4
--- /dev/null
+++ b/src/superxt.c
@@ -0,0 +1,60 @@
+/*This is the Chips and Technologies C82100 chipset used in the Amstrad PC5086 model*/
+#include "ibm.h"
+#include "io.h"
+#include "x86.h"
+#include "superxt.h"
+
+static uint8_t superxt_regs[256];
+static int superxt_index;
+static int superxt_emspage[4];
+
+void superxt_write(uint16_t port, uint8_t val, void *priv)
+{
+ switch (port)
+ {
+ case 0x22:
+ superxt_index = val;
+ break;
+
+ case 0x23:
+ superxt_regs[superxt_index] = val;
+
+ case 0x0208: case 0x4208: case 0x8208: case 0xC208:
+ superxt_emspage[port >> 14] = val;
+ break;
+
+ // default:
+ // pclog("%04X:%04X SUPERXT WRITE : %04X, %02X\n", CS, cpu_state.pc, port, val);
+ }
+}
+
+uint8_t superxt_read(uint16_t port, void *priv)
+{
+ switch (port)
+ {
+ case 0x22:
+ return superxt_index;
+
+ case 0x23:
+ return superxt_regs[superxt_index];
+
+ case 0x0208: case 0x4208: case 0x8208: case 0xC208:
+ return superxt_emspage[port >> 14];
+
+ // default:
+ // pclog("%04X:%04X SUPERXT READ : %04X\n", CS, cpu_state.pc, port);
+ }
+ return 0xff;
+}
+
+void superxt_init()
+{
+ /* Set register 0x42 to invalid configuration at startup */
+ superxt_regs[0x42] = 0;
+
+ io_sethandler(0x0022, 0x0002, superxt_read, NULL, NULL, superxt_write, NULL, NULL, NULL);
+ io_sethandler(0x0208, 0x0001, superxt_read, NULL, NULL, superxt_write, NULL, NULL, NULL);
+ io_sethandler(0x4208, 0x0001, superxt_read, NULL, NULL, superxt_write, NULL, NULL, NULL);
+ io_sethandler(0x8208, 0x0001, superxt_read, NULL, NULL, superxt_write, NULL, NULL, NULL);
+ io_sethandler(0xc208, 0x0001, superxt_read, NULL, NULL, superxt_write, NULL, NULL, NULL);
+}
diff --git a/src/superxt.h b/src/superxt.h
new file mode 100644
index 0000000..f21eb6a
--- /dev/null
+++ b/src/superxt.h
@@ -0,0 +1 @@
+void superxt_init();
diff --git a/src/thread.h b/src/thread.h
index fb47f28..0fe75aa 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -9,4 +9,10 @@ void thread_reset_event(event_t *_event);
int thread_wait_event(event_t *event, int timeout);
void thread_destroy_event(event_t *_event);
+typedef void mutex_t;
+mutex_t *thread_create_mutex(void);
+void thread_lock_mutex(mutex_t *mutex);
+void thread_unlock_mutex(mutex_t *mutex);
+void thread_destroy_mutex(mutex_t *mutex);
+
void thread_sleep(int t);
diff --git a/src/vid_ati18800.c b/src/vid_ati18800.c
index 7e672a0..2b30d4c 100644
--- a/src/vid_ati18800.c
+++ b/src/vid_ati18800.c
@@ -19,6 +19,10 @@ typedef struct ati18800_t
uint8_t regs[256];
int index;
+
+ int is_ega;
+ int ega_switches;
+ int ega_switch_read;
} ati18800_t;
void ati18800_out(uint16_t addr, uint8_t val, void *p)
@@ -56,6 +60,43 @@ void ati18800_out(uint16_t addr, uint8_t val, void *p)
}
break;
+ case 0x3c2:
+ if (ati18800->is_ega)
+ {
+ if ((val & 0x80) != (svga->miscout & 0x80))
+ {
+ int c;
+
+ if (val & 0x80)
+ {
+ for (c = 0; c < 256; c++)
+ {
+ ati18800->svga.pallook[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
+ ati18800->svga.pallook[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55);
+ }
+ ati18800->svga.vertical_linedbl = 0;
+ }
+ else
+ {
+ for (c = 0; c < 256; c++)
+ {
+ if ((c & 0x17) == 6)
+ ati18800->svga.pallook[c] = makecol32(0xaa, 0x55, 0x00);
+ else
+ {
+ ati18800->svga.pallook[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
+ ati18800->svga.pallook[c] += makecol32(((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55);
+ }
+ }
+ ati18800->svga.vertical_linedbl = 1;
+ }
+
+ svga->fullchange = changeframecount;
+ }
+ ati18800->ega_switch_read = val & 0xc;
+ }
+ break;
+
case 0x3D4:
svga->crtcreg = val & 0x3f;
return;
@@ -83,7 +124,7 @@ uint8_t ati18800_in(uint16_t addr, void *p)
{
ati18800_t *ati18800 = (ati18800_t *)p;
svga_t *svga = &ati18800->svga;
- uint8_t temp;
+ uint8_t temp = 0xff;
// if (addr != 0x3da) pclog("ati18800_in : %04X ", addr);
@@ -109,6 +150,20 @@ uint8_t ati18800_in(uint16_t addr, void *p)
}
break;
+ case 0x3c2:
+ if (ati18800->is_ega)
+ {
+ switch (ati18800->ega_switch_read)
+ {
+ case 0xc: return (ati18800->ega_switches & 1) ? 0x10 : 0;
+ case 0x8: return (ati18800->ega_switches & 2) ? 0x10 : 0;
+ case 0x4: return (ati18800->ega_switches & 4) ? 0x10 : 0;
+ case 0x0: return (ati18800->ega_switches & 8) ? 0x10 : 0;
+ }
+ }
+ break;
+
+
case 0x3D4:
temp = svga->crtcreg;
break;
@@ -119,10 +174,25 @@ uint8_t ati18800_in(uint16_t addr, void *p)
temp = svga_in(addr, svga);
break;
}
- if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,cpu_state.pc);
+// if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,cpu_state.pc);
return temp;
}
+static void ega_wonder_800_recalctimings(svga_t *svga)
+{
+ ati18800_t *ati18800 = (ati18800_t *)svga->p;
+ int clksel = ((svga->miscout & 0xc) >> 2) | ((ati18800->regs[0xbe] & 0x10) ? 4 : 0);
+
+ switch (clksel)
+ {
+ case 0: svga->clock = (cpuclock * (double)(1ull << 32)) / 25175000.0; break;
+ case 1: svga->clock = (cpuclock * (double)(1ull << 32)) / 28322000.0; break;
+ case 4: svga->clock = (cpuclock * (double)(1ull << 32)) / 14318181.0; break;
+ case 5: svga->clock = (cpuclock * (double)(1ull << 32)) / 16257000.0; break;
+ case 7: default: svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; break;
+ }
+}
+
void *ati18800_init()
{
ati18800_t *ati18800 = malloc(sizeof(ati18800_t));
@@ -146,11 +216,51 @@ void *ati18800_init()
return ati18800;
}
+void *ega_wonder_800_init()
+{
+ int c;
+
+ ati18800_t *ati18800 = malloc(sizeof(ati18800_t));
+ memset(ati18800, 0, sizeof(ati18800_t));
+
+ rom_init(&ati18800->bios_rom, "ATI EGA Wonder 800+ N1.00.BIN", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
+
+ svga_init(&ati18800->svga, ati18800, 1 << 18, /*256kb*/
+ ega_wonder_800_recalctimings,
+ ati18800_in, ati18800_out,
+ NULL,
+ NULL);
+
+ io_sethandler(0x01ce, 0x0002, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
+ io_sethandler(0x03c0, 0x0006, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
+ io_sethandler(0x03ca, 0x0016, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800);
+
+ ati18800->svga.miscout = 1;
+
+ for (c = 0; c < 256; c++)
+ {
+ ati18800->svga.pallook[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
+ ati18800->svga.pallook[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55);
+ }
+
+ ati_eeprom_load(&ati18800->eeprom, "egawonder800.nvr", 0);
+
+ ati18800->is_ega = 1;
+ ati18800->ega_switches = 9;
+
+ return ati18800;
+}
+
static int ati18800_available()
{
return rom_present("vgaedge16.vbi");
}
+static int ega_wonder_800_available()
+{
+ return rom_present("ATI EGA Wonder 800+ N1.00.BIN");
+}
+
void ati18800_close(void *p)
{
ati18800_t *ati18800 = (ati18800_t *)p;
@@ -193,3 +303,14 @@ device_t ati18800_device =
ati18800_add_status_info
};
+device_t ati_ega_wonder_800_device =
+{
+ "ATI EGA Wonder 800+",
+ 0,
+ ega_wonder_800_init,
+ ati18800_close,
+ ega_wonder_800_available,
+ ati18800_speed_changed,
+ ati18800_force_redraw,
+ ati18800_add_status_info
+};
diff --git a/src/vid_ati18800.h b/src/vid_ati18800.h
index 83fe2c0..0d667ab 100644
--- a/src/vid_ati18800.h
+++ b/src/vid_ati18800.h
@@ -1 +1,2 @@
extern device_t ati18800_device;
+extern device_t ati_ega_wonder_800_device;
diff --git a/src/vid_ati28800.c b/src/vid_ati28800.c
index 275432d..55ccad0 100644
--- a/src/vid_ati28800.c
+++ b/src/vid_ati28800.c
@@ -140,7 +140,7 @@ void ati28800k_out(uint16_t addr, uint8_t val, void *p)
case 0x3DE:
// pclog("ati28800k_out : set port 03DE to %02X at %04X:%04X\n", val, CS, cpu_state.oldpc);
ati28800->in_get_korean_font_kind_set = 0;
- if(ati28800->get_korean_font_enabled && (ati28800->regs[0xBF] & 0x20))
+ if(ati28800->get_korean_font_enabled)
{
if((ati28800->get_korean_font_base & 0x7F) > 0x20 && (ati28800->get_korean_font_base & 0x7F) < 0x7F)
fontdatksc5601_user[(ati28800->get_korean_font_kind & 4) * 24 + (ati28800->get_korean_font_base & 0x7F) - 0x20][ati28800->get_korean_font_index] = val;
@@ -237,7 +237,7 @@ uint8_t ati28800k_in(uint16_t addr, void *p)
switch (addr)
{
case 0x3DE:
- if (ati28800->get_korean_font_enabled && (ati28800->regs[0xBF] & 0x20))
+ if (ati28800->get_korean_font_enabled)
{
switch (ati28800->get_korean_font_kind >> 8)
{
@@ -268,24 +268,24 @@ uint8_t ati28800k_in(uint16_t addr, void *p)
void ati28800_recalctimings(svga_t *svga)
{
ati28800_t *ati28800 = (ati28800_t *)svga->p;
- pclog("ati28800_recalctimings\n");
+ //pclog("ati28800_recalctimings\n");
switch (((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->regs[0xb9] & 2) << 1) | ((svga->miscout & 0x0C) >> 2))
{
- case 0x00: svga->clock = cpuclock / 42954000.0; break;
- case 0x01: svga->clock = cpuclock / 48771000.0; break;
- case 0x03: svga->clock = cpuclock / 36000000.0; break;
- case 0x04: svga->clock = cpuclock / 50350000.0; break;
- case 0x05: svga->clock = cpuclock / 56640000.0; break;
- case 0x07: svga->clock = cpuclock / 44900000.0; break;
- case 0x08: svga->clock = cpuclock / 30240000.0; break;
- case 0x09: svga->clock = cpuclock / 32000000.0; break;
- case 0x0A: svga->clock = cpuclock / 37500000.0; break;
- case 0x0B: svga->clock = cpuclock / 39000000.0; break;
- case 0x0C: svga->clock = cpuclock / 40000000.0; break;
- case 0x0D: svga->clock = cpuclock / 56644000.0; break;
- case 0x0E: svga->clock = cpuclock / 75000000.0; break;
- case 0x0F: svga->clock = cpuclock / 65000000.0; break;
+ case 0x00: svga->clock = (cpuclock * (double)(1ull << 32)) / 42954000.0; break;
+ case 0x01: svga->clock = (cpuclock * (double)(1ull << 32)) / 48771000.0; break;
+ case 0x03: svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; break;
+ case 0x04: svga->clock = (cpuclock * (double)(1ull << 32)) / 50350000.0; break;
+ case 0x05: svga->clock = (cpuclock * (double)(1ull << 32)) / 56640000.0; break;
+ case 0x07: svga->clock = (cpuclock * (double)(1ull << 32)) / 44900000.0; break;
+ case 0x08: svga->clock = (cpuclock * (double)(1ull << 32)) / 30240000.0; break;
+ case 0x09: svga->clock = (cpuclock * (double)(1ull << 32)) / 32000000.0; break;
+ case 0x0A: svga->clock = (cpuclock * (double)(1ull << 32)) / 37500000.0; break;
+ case 0x0B: svga->clock = (cpuclock * (double)(1ull << 32)) / 39000000.0; break;
+ case 0x0C: svga->clock = (cpuclock * (double)(1ull << 32)) / 50350000.0; break;
+ case 0x0D: svga->clock = (cpuclock * (double)(1ull << 32)) / 56644000.0; break;
+ case 0x0E: svga->clock = (cpuclock * (double)(1ull << 32)) / 75000000.0; break;
+ case 0x0F: svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; break;
default: break;
}
if (ati28800->regs[0xb8] & 0x40)
@@ -297,18 +297,9 @@ void ati28800_recalctimings(svga_t *svga)
svga->rowoffset <<= 1;
}
- if (svga->crtc[0x17] & 4)
- {
- svga->vtotal <<= 1;
- svga->dispend <<= 1;
- svga->vsyncstart <<= 1;
- svga->split <<= 1;
- svga->vblankstart <<= 1;
- }
-
if (!svga->scrblank && (ati28800->regs[0xb0] & 0x20)) /*Extended 256 colour modes*/
{
- pclog("8bpp_highres\n");
+ //pclog("8bpp_highres\n");
svga->render = svga_render_8bpp_highres;
svga->rowoffset <<= 1;
svga->ma <<= 1;
@@ -364,7 +355,7 @@ void *ati28800k_init()
ati28800->ksc5601_mode_enabled = 0;
rom_init(&ati28800->bios_rom, "atikorvga.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
- loadfont("ati_ksc5601.rom", 6);
+ loadfont("ati_ksc5601.rom", FONT_KSC5601);
svga_init(&ati28800->svga, ati28800, 1 << 19, /*512kb*/
ati28800k_recalctimings,
@@ -376,12 +367,91 @@ void *ati28800k_init()
io_sethandler(0x03c0, 0x0020, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800);
ati28800->svga.miscout = 1;
+ ati28800->svga.ksc5601_sbyte_mask = 0;
+ ati28800->svga.ksc5601_udc_area_msb[0] = 0xC9;
+ ati28800->svga.ksc5601_udc_area_msb[1] = 0xFE;
+ ati28800->svga.ksc5601_swap_mode = 0;
+ ati28800->svga.ksc5601_english_font_type = 0;
ati_eeprom_load(&ati28800->eeprom, "atikorvga.nvr", 0);
return ati28800;
}
+void *ati28800k_spc4620p_init()
+{
+ ati28800_t *ati28800 = malloc(sizeof(ati28800_t));
+ memset(ati28800, 0, sizeof(ati28800_t));
+
+ ati28800->port_03dd_val = 0;
+ ati28800->get_korean_font_base = 0;
+ ati28800->get_korean_font_index = 0;
+ ati28800->get_korean_font_enabled = 0;
+ ati28800->get_korean_font_kind = 0;
+ ati28800->in_get_korean_font_kind_set = 0;
+ ati28800->ksc5601_mode_enabled = 0;
+
+ rom_init_interleaved(&ati28800->bios_rom, "spc4620p/31005h.u8", "spc4620p/31005h.u10", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
+ loadfont("spc4620p/svb6120a_font.rom", 6);
+
+ svga_init(&ati28800->svga, ati28800, 1 << 19, /*512kb*/
+ ati28800k_recalctimings,
+ ati28800k_in, ati28800k_out,
+ NULL,
+ NULL);
+
+ io_sethandler(0x01ce, 0x0002, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800);
+ io_sethandler(0x03c0, 0x0020, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800);
+
+ ati28800->svga.miscout = 1;
+ ati28800->svga.ksc5601_sbyte_mask = 0;
+ ati28800->svga.ksc5601_udc_area_msb[0] = 0xC9;
+ ati28800->svga.ksc5601_udc_area_msb[1] = 0xFE;
+ ati28800->svga.ksc5601_swap_mode = 0;
+ ati28800->svga.ksc5601_english_font_type = 0;
+
+ ati_eeprom_load(&ati28800->eeprom, "svb6120a.nvr", 0);
+
+ return ati28800;
+}
+
+void *ati28800k_spc6033p_init()
+{
+ ati28800_t *ati28800 = malloc(sizeof(ati28800_t));
+ memset(ati28800, 0, sizeof(ati28800_t));
+
+ ati28800->port_03dd_val = 0;
+ ati28800->get_korean_font_base = 0;
+ ati28800->get_korean_font_index = 0;
+ ati28800->get_korean_font_enabled = 0;
+ ati28800->get_korean_font_kind = 0;
+ ati28800->in_get_korean_font_kind_set = 0;
+ ati28800->ksc5601_mode_enabled = 0;
+
+ rom_init(&ati28800->bios_rom, "spc6033p/phoenix.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
+ loadfont("spc6033p/svb6120a_font.rom", 6);
+
+ svga_init(&ati28800->svga, ati28800, 1 << 19, /*512kb*/
+ ati28800k_recalctimings,
+ ati28800k_in, ati28800k_out,
+ NULL,
+ NULL);
+
+ io_sethandler(0x01ce, 0x0002, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800);
+ io_sethandler(0x03c0, 0x0020, ati28800k_in, NULL, NULL, ati28800k_out, NULL, NULL, ati28800);
+
+ ati28800->svga.miscout = 1;
+ ati28800->svga.ksc5601_sbyte_mask = 0;
+ ati28800->svga.ksc5601_udc_area_msb[0] = 0xC9;
+ ati28800->svga.ksc5601_udc_area_msb[1] = 0xFE;
+ ati28800->svga.ksc5601_swap_mode = 0;
+ ati28800->svga.ksc5601_english_font_type = 0;
+
+ ati_eeprom_load(&ati28800->eeprom, "svb6120a_spc6033p.nvr", 0);
+
+ return ati28800;
+}
+
static int ati28800_available()
{
return rom_present("bios.bin");
@@ -456,3 +526,27 @@ device_t ati28800k_device =
ati28800_force_redraw,
ati28800k_add_status_info
};
+
+device_t ati28800k_spc4620p_device =
+{
+ "SVB-6120A",
+ 0,
+ ati28800k_spc4620p_init,
+ ati28800_close,
+ NULL,
+ ati28800_speed_changed,
+ ati28800_force_redraw,
+ ati28800k_add_status_info
+};
+
+device_t ati28800k_spc6033p_device =
+{
+ "SVB-6120A",
+ 0,
+ ati28800k_spc6033p_init,
+ ati28800_close,
+ NULL,
+ ati28800_speed_changed,
+ ati28800_force_redraw,
+ ati28800k_add_status_info
+};
diff --git a/src/vid_ati28800.h b/src/vid_ati28800.h
index 51f3615..2d2cd8a 100644
--- a/src/vid_ati28800.h
+++ b/src/vid_ati28800.h
@@ -1,2 +1,4 @@
extern device_t ati28800_device;
extern device_t ati28800k_device;
+extern device_t ati28800k_spc4620p_device;
+extern device_t ati28800k_spc6033p_device;
diff --git a/src/vid_ati_eeprom.c b/src/vid_ati_eeprom.c
index 3586894..ce13701 100644
--- a/src/vid_ati_eeprom.c
+++ b/src/vid_ati_eeprom.c
@@ -37,7 +37,7 @@ void ati_eeprom_load(ati_eeprom_t *eeprom, char *fn, int type)
f = nvrfopen(eeprom->fn, "rb");
if (!f)
{
- memset(eeprom->data, 0, eeprom->type ? 512 : 128);
+ memset(eeprom->data, 0xff, eeprom->type ? 512 : 128);
return;
}
fread(eeprom->data, 1, eeprom->type ? 512 : 128, f);
diff --git a/src/vid_ati_mach64.c b/src/vid_ati_mach64.c
index e38fca3..8b752f2 100644
--- a/src/vid_ati_mach64.c
+++ b/src/vid_ati_mach64.c
@@ -8,6 +8,7 @@
#include "rom.h"
#include "thread.h"
#include "video.h"
+#include "vid_ddc.h"
#include "vid_svga.h"
#include "vid_svga_render.h"
#include "vid_ati68860_ramdac.h"
@@ -1838,11 +1839,27 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p)
else
ret = ati68860_ramdac_in(addr & 3, &mach64->ramdac, &mach64->svga);
break;
- case 0xc4: case 0xc5: case 0xc6: case 0xc7:
- if (mach64->type == MACH64_VT2)
- mach64->dac_cntl |= (4 << 24);
+ case 0xc4: case 0xc5: case 0xc6:
READ8(addr, mach64->dac_cntl);
break;
+ case 0xc7:
+ READ8(addr, mach64->dac_cntl);
+ if (mach64->type == MACH64_VT2)
+ {
+ uint8_t gpio_state = 6;
+
+ if ((ret & (1 << 4)) && !(ret & (1 << 1)))
+ gpio_state &= ~(1 << 1);
+ if (!(ret & (1 << 4)) && !ddc_read_data())
+ gpio_state &= ~(1 << 1);
+ if ((ret & (1 << 5)) && !(ret & (1 << 2)))
+ gpio_state &= ~(1 << 2);
+ if (!(ret & (1 << 5)) && !ddc_read_clock())
+ gpio_state &= ~(1 << 2);
+
+ ret = (ret & ~6) | gpio_state;
+ }
+ break;
case 0xd0: case 0xd1: case 0xd2: case 0xd3:
READ8(addr, mach64->gen_test_cntl);
@@ -2354,6 +2371,12 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p)
WRITE8(addr, mach64->dac_cntl, val);
svga_set_ramdac_type(svga, (mach64->dac_cntl & 0x100) ? RAMDAC_8BIT : RAMDAC_6BIT);
ati68860_set_ramdac_type(&mach64->ramdac, (mach64->dac_cntl & 0x100) ? RAMDAC_8BIT : RAMDAC_6BIT);
+ {
+ int data = (val & (1 << 4)) ? ((val & (1 << 1)) ? 1 : 0) : 1;
+ int clk = (val & (1 << 5)) ? ((val & (1 << 2)) ? 1 : 0) : 1;
+
+ ddc_i2c_change(clk, data);
+ }
break;
case 0xd0: case 0xd1: case 0xd2: case 0xd3:
@@ -3397,6 +3420,8 @@ static void *mach64_common_init()
mach64->wake_fifo_thread = thread_create_event();
mach64->fifo_not_full_event = thread_create_event();
mach64->fifo_thread = thread_create(fifo_thread, mach64);
+
+ ddc_init();
return mach64;
}
diff --git a/src/vid_cga.c b/src/vid_cga.c
index 29f6ecb..a74f497 100644
--- a/src/vid_cga.c
+++ b/src/vid_cga.c
@@ -28,10 +28,10 @@ void cga_out(uint16_t addr, uint8_t val, void *p)
// pclog("CGA_OUT %04X %02X\n", addr, val);
switch (addr)
{
- case 0x3D4:
+ case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6:
cga->crtcreg = val & 31;
return;
- case 0x3D5:
+ case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7:
old = cga->crtc[cga->crtcreg];
cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg];
if (old != val)
@@ -171,8 +171,13 @@ void cga_poll(void *p)
{
for (x = 0; x < cga->crtc[1]; x++)
{
- chr = cga->charbuffer[x << 1];
- attr = cga->charbuffer[(x << 1) + 1];
+ if (cga->cgamode & 8)
+ {
+ chr = cga->charbuffer[x << 1];
+ attr = cga->charbuffer[(x << 1) + 1];
+ }
+ else
+ chr = attr = 0;
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
if (cga->cgamode & 0x20)
{
@@ -203,8 +208,13 @@ void cga_poll(void *p)
{
for (x = 0; x < cga->crtc[1]; x++)
{
- chr = cga->vram[((cga->ma << 1) & 0x3fff)];
- attr = cga->vram[(((cga->ma << 1) + 1) & 0x3fff)];
+ if (cga->cgamode & 8)
+ {
+ chr = cga->vram[((cga->ma << 1) & 0x3fff)];
+ attr = cga->vram[(((cga->ma << 1) + 1) & 0x3fff)];
+ }
+ else
+ chr = attr = 0;
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
if (cga->cgamode & 0x20)
{
@@ -257,7 +267,10 @@ void cga_poll(void *p)
}
for (x = 0; x < cga->crtc[1]; x++)
{
- dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
+ if (cga->cgamode & 8)
+ dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
+ else
+ dat = 0;
cga->ma++;
for (c = 0; c < 8; c++)
{
@@ -273,7 +286,10 @@ void cga_poll(void *p)
cols[1] = cga->cgacol & 15;
for (x = 0; x < cga->crtc[1]; x++)
{
- dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
+ if (cga->cgamode & 8)
+ dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
+ else
+ dat = 0;
cga->ma++;
for (c = 0; c < 16; c++)
{
diff --git a/src/vid_cl5429.c b/src/vid_cl5429.c
index c9a20d5..51584cd 100644
--- a/src/vid_cl5429.c
+++ b/src/vid_cl5429.c
@@ -1,9 +1,11 @@
/*Cirrus Logic CL-GD5429 emulation*/
+//SR7.0 = "true packed-pixel memory addressing"
#include
#include "ibm.h"
#include "cpu.h"
#include "device.h"
#include "io.h"
+#include "mca.h"
#include "mem.h"
#include "pci.h"
#include "rom.h"
@@ -11,11 +13,15 @@
#include "vid_cl5429.h"
#include "vid_svga.h"
#include "vid_svga_render.h"
+#include "vid_vga.h"
#include "vid_unk_ramdac.h"
enum
{
- CL_TYPE_GD5429 = 0,
+ CL_TYPE_AVGA2 = 0,
+ CL_TYPE_GD5426,
+ CL_TYPE_GD5428,
+ CL_TYPE_GD5429,
CL_TYPE_GD5430,
CL_TYPE_GD5434
};
@@ -24,6 +30,10 @@ enum
#define BLIT_DEPTH_16 1
#define BLIT_DEPTH_32 3
+#define CL_GD5428_SYSTEM_BUS_MCA 5
+#define CL_GD5428_SYSTEM_BUS_VESA 6
+#define CL_GD5428_SYSTEM_BUS_ISA 7
+
#define CL_GD5429_SYSTEM_BUS_VESA 5
#define CL_GD5429_SYSTEM_BUS_ISA 7
@@ -49,7 +59,8 @@ typedef struct gd5429_t
struct
{
- uint32_t bg_col, fg_col;
+ uint32_t bg_col, fg_col;
+ uint16_t trans_col, trans_mask;
uint16_t width, height;
uint16_t dst_pitch, src_pitch;
uint32_t dst_addr, src_addr;
@@ -59,6 +70,9 @@ typedef struct gd5429_t
uint16_t width_backup, height_internal;
int x_count, y_count;
int depth;
+
+ int mem_word_sel;
+ uint16_t mem_word_save;
} blt;
uint8_t hidden_dac_reg;
@@ -68,11 +82,25 @@ typedef struct gd5429_t
uint8_t int_line;
int card;
+ uint8_t pos_regs[8];
+ svga_t *mb_vga;
+
uint32_t lfb_base;
int mmio_vram_overlap;
+
+ uint8_t sr10_read, sr11_read;
+
+ uint8_t latch_ext[4];
+
+ int vidsys_ena;
} gd5429_t;
+#define GRB_X8_ADDRESSING (1 << 1)
+#define GRB_WRITEMODE_EXT (1 << 2)
+#define GRB_8B_LATCHES (1 << 3)
+#define GRB_ENHANCED_16BIT (1 << 4)
+
static void gd5429_mmio_write(uint32_t addr, uint8_t val, void *p);
static void gd5429_mmio_writew(uint32_t addr, uint16_t val, void *p);
static void gd5429_mmio_writel(uint32_t addr, uint32_t val, void *p);
@@ -86,19 +114,31 @@ void gd5429_blt_write_l(uint32_t addr, uint32_t val, void *p);
void gd5429_recalc_banking(gd5429_t *gd5429);
void gd5429_recalc_mapping(gd5429_t *gd5429);
+uint8_t gd5429_read_linear(uint32_t addr, void *p);
+
+static void ibm_gd5428_mapping_update(gd5429_t *gd5429);
+
void gd5429_out(uint16_t addr, uint8_t val, void *p)
{
gd5429_t *gd5429 = (gd5429_t *)p;
svga_t *svga = &gd5429->svga;
uint8_t old;
- if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
+ if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
// pclog("gd5429 out %04X %02X\n", addr, val);
switch (addr)
{
+ case 0x3c3:
+ if (MCA)
+ {
+ gd5429->vidsys_ena = val & 1;
+ ibm_gd5428_mapping_update(gd5429);
+ }
+ break;
+
case 0x3c4:
svga->seqaddr = val;
break;
@@ -111,28 +151,40 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p)
case 0x10: case 0x30: case 0x50: case 0x70:
case 0x90: case 0xb0: case 0xd0: case 0xf0:
svga->hwcursor.x = (val << 3) | ((svga->seqaddr >> 5) & 7);
+ gd5429->sr10_read = svga->seqaddr & 0xe0;
// pclog("svga->hwcursor.x = %i\n", svga->hwcursor.x);
break;
case 0x11: case 0x31: case 0x51: case 0x71:
case 0x91: case 0xb1: case 0xd1: case 0xf1:
svga->hwcursor.y = (val << 3) | ((svga->seqaddr >> 5) & 7);
+ gd5429->sr11_read = svga->seqaddr & 0xe0;
// pclog("svga->hwcursor.y = %i\n", svga->hwcursor.y);
break;
case 0x12:
svga->hwcursor.ena = val & 1;
svga->hwcursor.ysize = (val & 4) ? 64 : 32;
svga->hwcursor.yoff = 0;
+ if (svga->hwcursor.ysize == 64)
+ svga->hwcursor.addr = (0x3fc000 + ((svga->seqregs[0x13] & 0x3c) * 256)) & svga->vram_mask;
+ else
+ svga->hwcursor.addr = (0x3fc000 + ((svga->seqregs[0x13] & 0x3f) * 256)) & svga->vram_mask;
// pclog("svga->hwcursor.ena = %i\n", svga->hwcursor.ena);
break;
case 0x13:
- svga->hwcursor.addr = (0x3fc000 + ((val & 0x3f) * 256)) & svga->vram_mask;
+ if (svga->hwcursor.ysize == 64)
+ svga->hwcursor.addr = (0x3fc000 + ((val & 0x3c) * 256)) & svga->vram_mask;
+ else
+ svga->hwcursor.addr = (0x3fc000 + ((val & 0x3f) * 256)) & svga->vram_mask;
// pclog("svga->hwcursor.addr = %x\n", svga->hwcursor.addr);
break;
case 0x07:
svga->set_reset_disabled = svga->seqregs[7] & 1;
+ svga->packed_chain4 = svga->seqregs[7] & 1;
+ svga_recalctimings(svga);
case 0x17:
- gd5429_recalc_mapping(gd5429);
+ if (gd5429->type >= CL_TYPE_GD5429)
+ gd5429_recalc_mapping(gd5429);
break;
}
return;
@@ -150,7 +202,10 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p)
}
gd5429->dac_3c6_count = 0;
break;
-
+ case 0x3c7: case 0x3c8: case 0x3c9:
+ gd5429->dac_3c6_count = 0;
+ break;
+
case 0x3cf:
// pclog("Write GDC %02x %02x\n", svga->gdcaddr, val);
if (svga->gdcaddr == 0)
@@ -176,12 +231,28 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p)
svga->gdcreg[6] = val;
gd5429_recalc_mapping(gd5429);
}
+
+ /*Hack - the Windows 3.x drivers for the GD5426/8 require VRAM wraparound
+ for pattern & cursor writes to work correctly, but the BIOSes require
+ no wrapping to detect memory size - albeit with odd/even mode enabled.
+ This may be a quirk of address mapping. So change wrapping mode based on
+ odd/even mode for now*/
+ if (gd5429->type == CL_TYPE_GD5426 || gd5429->type == CL_TYPE_GD5428)
+ {
+ if (val & 2) /*Odd/Even*/
+ svga->decode_mask = 0x1fffff;
+ else
+ svga->decode_mask = svga->vram_mask;
+ }
+
svga->gdcreg[6] = val;
return;
}
if (svga->gdcaddr > 8)
{
svga->gdcreg[svga->gdcaddr & 0x3f] = val;
+ if (gd5429->type < CL_TYPE_GD5426 && (svga->gdcaddr > 0xb))
+ return;
switch (svga->gdcaddr)
{
case 0x09: case 0x0a: case 0x0b:
@@ -270,7 +341,24 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p)
case 0x31:
gd5429_mmio_write(0xb8040, val, gd5429);
break;
- }
+
+ case 0x34:
+ if (gd5429->type <= CL_TYPE_GD5428)
+ gd5429->blt.trans_col = (gd5429->blt.trans_col & 0xff00) | val;
+ break;
+ case 0x35:
+ if (gd5429->type <= CL_TYPE_GD5428)
+ gd5429->blt.trans_col = (gd5429->blt.trans_col & 0x00ff) | (val << 8);
+ break;
+ case 0x36:
+ if (gd5429->type <= CL_TYPE_GD5428)
+ gd5429->blt.trans_mask = (gd5429->blt.trans_mask & 0xff00) | val;
+ break;
+ case 0x37:
+ if (gd5429->type <= CL_TYPE_GD5428)
+ gd5429->blt.trans_mask = (gd5429->blt.trans_mask & 0x00ff) | (val << 8);
+ break;
+ }
return;
}
break;
@@ -304,13 +392,25 @@ uint8_t gd5429_in(uint16_t addr, void *p)
gd5429_t *gd5429 = (gd5429_t *)p;
svga_t *svga = &gd5429->svga;
- if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3d0) && !(svga->miscout & 1))
+ if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
// if (addr != 0x3da) pclog("IN gd5429 %04X\n", addr);
switch (addr)
{
+ case 0x3c3:
+ if (MCA)
+ return gd5429->vidsys_ena;
+ break;
+
+ case 0x3c4:
+ if ((svga->seqaddr & 0x1f) == 0x10)
+ return (svga->seqaddr & 0x1f) | gd5429->sr10_read;
+ if ((svga->seqaddr & 0x1f) == 0x11)
+ return (svga->seqaddr & 0x1f) | gd5429->sr11_read;
+ return svga->seqaddr & 0x1f;
+
case 0x3c5:
if (svga->seqaddr > 5)
{
@@ -322,9 +422,20 @@ uint8_t gd5429_in(uint16_t addr, void *p)
return ((svga->seqregs[6] & 0x17) == 0x12) ? 0x12 : 0x0f;
case 0x17:
- temp = svga->gdcreg[0x17];
+ if (gd5429->type < CL_TYPE_GD5426)
+ break;
+ temp = svga->seqregs[0x17];
temp &= ~(7 << 3);
- if (gd5429->type == CL_TYPE_GD5429)
+ if (gd5429->type == CL_TYPE_GD5426 || gd5429->type == CL_TYPE_GD5428)
+ {
+ if (MCA)
+ temp |= (CL_GD5428_SYSTEM_BUS_MCA << 3);
+ else if (has_vlb)
+ temp |= (CL_GD5428_SYSTEM_BUS_VESA << 3);
+ else
+ temp |= (CL_GD5428_SYSTEM_BUS_ISA << 3);
+ }
+ else if (gd5429->type == CL_TYPE_GD5429)
{
if (has_vlb)
temp |= (CL_GD5429_SYSTEM_BUS_VESA << 3);
@@ -355,6 +466,9 @@ uint8_t gd5429_in(uint16_t addr, void *p)
}
gd5429->dac_3c6_count++;
break;
+ case 0x3c7: case 0x3c8: case 0x3c9:
+ gd5429->dac_3c6_count = 0;
+ break;
case 0x3cf:
if (svga->gdcaddr > 8)
@@ -371,6 +485,12 @@ uint8_t gd5429_in(uint16_t addr, void *p)
case 0x27: /*ID*/
switch (gd5429->type)
{
+ case CL_TYPE_AVGA2:
+ return 0x18; /*AVGA2*/
+ case CL_TYPE_GD5426:
+ return 0x90; /*GD5426*/
+ case CL_TYPE_GD5428:
+ return 0x98; /*GD5428*/
case CL_TYPE_GD5429:
return 0x9c; /*GD5429*/
case CL_TYPE_GD5430:
@@ -413,7 +533,8 @@ void gd5429_recalc_mapping(gd5429_t *gd5429)
{
svga_t *svga = &gd5429->svga;
- if (PCI && !(gd5429->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))
+ if ((PCI && gd5429->type >= CL_TYPE_GD5430 && !(gd5429->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) ||
+ (MCA && (!(gd5429->pos_regs[2] & 0x01) || !gd5429->vidsys_ena)))
{
mem_mapping_disable(&svga->mapping);
mem_mapping_disable(&gd5429->linear_mapping);
@@ -447,7 +568,7 @@ void gd5429_recalc_mapping(gd5429_t *gd5429)
gd5429->mmio_vram_overlap = 1;
break;
}
- if (svga->seqregs[0x17] & 0x04)
+ if (gd5429->type >= CL_TYPE_GD5429 && svga->seqregs[0x17] & 0x04)
mem_mapping_set_addr(&gd5429->mmio_mapping, 0xb8000, 0x00100);
else
mem_mapping_disable(&gd5429->mmio_mapping);
@@ -476,7 +597,7 @@ void gd5429_recalc_mapping(gd5429_t *gd5429)
}
mem_mapping_disable(&svga->mapping);
mem_mapping_set_addr(&gd5429->linear_mapping, base, size);
- if (svga->seqregs[0x17] & 0x04)
+ if (gd5429->type >= CL_TYPE_GD5429 && svga->seqregs[0x17] & 0x04)
mem_mapping_set_addr(&gd5429->mmio_mapping, 0xb8000, 0x00100);
else
mem_mapping_disable(&gd5429->mmio_mapping);
@@ -544,8 +665,12 @@ void gd5429_recalctimings(svga_t *svga)
n = svga->seqregs[0xb + clock] & 0x7f;
d = (svga->seqregs[0x1b + clock] >> 1) & 0x1f;
p = svga->seqregs[0x1b + clock] & 1;
-
- vclk = (14318184.0 * ((float)n / (float)d)) / (float)(1 + p);
+
+ /*Prevent divide by zero during clock setup*/
+ if (d && n)
+ vclk = (14318184.0 * ((float)n / (float)d)) / (float)(1 + p);
+ else
+ vclk = 14318184.0;
switch (svga->seqregs[7] & ((gd5429->type >= CL_TYPE_GD5434) ? 0xe : 0x6))
{
case 2:
@@ -566,33 +691,61 @@ void gd5429_hwcursor_draw(svga_t *svga, int displine)
uint8_t dat[2];
int xx;
int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
+ int line_offset = (svga->seqregs[0x12] & 0x04) ? 16 : 4;
if (svga->interlace && svga->hwcursor_oddeven)
- svga->hwcursor_latch.addr += 4;
+ svga->hwcursor_latch.addr += line_offset;
- for (x = 0; x < 32; x += 8)
+ if (svga->seqregs[0x12] & 0x04)
{
- dat[0] = svga->vram[svga->hwcursor_latch.addr];
- dat[1] = svga->vram[svga->hwcursor_latch.addr + 0x80];
- for (xx = 0; xx < 8; xx++)
+ for (x = 0; x < 64; x += 8)
{
- if (offset >= svga->hwcursor_latch.x)
+ dat[0] = svga->vram[svga->hwcursor_latch.addr];
+ dat[1] = svga->vram[svga->hwcursor_latch.addr + 8];
+ for (xx = 0; xx < 8; xx++)
{
- if (dat[1] & 0x80)
- ((uint32_t *)buffer32->line[displine])[offset + 32] = 0;
- if (dat[0] & 0x80)
- ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff;
+ if (offset >= svga->hwcursor_latch.x)
+ {
+ if (dat[1] & 0x80)
+ ((uint32_t *)buffer32->line[displine])[offset + 32] = 0;
+ if (dat[0] & 0x80)
+ ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff;
+ }
+
+ offset++;
+ dat[0] <<= 1;
+ dat[1] <<= 1;
}
-
- offset++;
- dat[0] <<= 1;
- dat[1] <<= 1;
+ svga->hwcursor_latch.addr++;
+ }
+ svga->hwcursor_latch.addr += 8;
+ }
+ else
+ {
+ for (x = 0; x < 32; x += 8)
+ {
+ dat[0] = svga->vram[svga->hwcursor_latch.addr];
+ dat[1] = svga->vram[svga->hwcursor_latch.addr + 0x80];
+ for (xx = 0; xx < 8; xx++)
+ {
+ if (offset >= svga->hwcursor_latch.x)
+ {
+ if (dat[1] & 0x80)
+ ((uint32_t *)buffer32->line[displine])[offset + 32] = 0;
+ if (dat[0] & 0x80)
+ ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff;
+ }
+
+ offset++;
+ dat[0] <<= 1;
+ dat[1] <<= 1;
+ }
+ svga->hwcursor_latch.addr++;
}
- svga->hwcursor_latch.addr++;
}
if (svga->interlace && !svga->hwcursor_oddeven)
- svga->hwcursor_latch.addr += 4;
+ svga->hwcursor_latch.addr += line_offset;
}
@@ -602,10 +755,10 @@ static void gd5429_write(uint32_t addr, uint8_t val, void *p)
{
gd5429_t *gd5429 = (gd5429_t *)p;
svga_t *svga = &gd5429->svga;
-// pclog("gd5429_write : %05X %02X ", addr, val);
+
addr &= svga->banked_mask;
addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1];
-// pclog("%08X\n", addr);
+
gd5429_write_linear(addr, val, p);
}
static void gd5429_writew(uint32_t addr, uint16_t val, void *p)
@@ -616,7 +769,7 @@ static void gd5429_writew(uint32_t addr, uint16_t val, void *p)
addr &= svga->banked_mask;
addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1];
- if (svga->writemode < 4)
+ if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
svga_writew_linear(addr, val, svga);
else
{
@@ -632,7 +785,7 @@ static void gd5429_writel(uint32_t addr, uint32_t val, void *p)
addr &= svga->banked_mask;
addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1];
- if (svga->writemode < 4)
+ if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
svga_writel_linear(addr, val, svga);
else
{
@@ -647,13 +800,10 @@ static uint8_t gd5429_read(uint32_t addr, void *p)
{
gd5429_t *gd5429 = (gd5429_t *)p;
svga_t *svga = &gd5429->svga;
- uint8_t ret;
-// pclog("gd5429_read : %05X ", addr);
+
addr &= svga->banked_mask;
addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1];
- ret = svga_read_linear(addr, &gd5429->svga);
-// pclog("%08X %02X\n", addr, ret);
- return ret;
+ return gd5429_read_linear(addr, gd5429);
}
static uint16_t gd5429_readw(uint32_t addr, void *p)
{
@@ -662,7 +812,10 @@ static uint16_t gd5429_readw(uint32_t addr, void *p)
addr &= svga->banked_mask;
addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1];
- return svga_readw_linear(addr, &gd5429->svga);
+
+ if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ return svga_readw_linear(addr, &gd5429->svga);
+ return gd5429_read_linear(addr, gd5429) | (gd5429_read_linear(addr+1, gd5429) << 8);
}
static uint32_t gd5429_readl(uint32_t addr, void *p)
{
@@ -671,7 +824,11 @@ static uint32_t gd5429_readl(uint32_t addr, void *p)
addr &= svga->banked_mask;
addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1];
- return svga_readl_linear(addr, &gd5429->svga);
+
+ if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ return svga_readl_linear(addr, &gd5429->svga);
+ return gd5429_read_linear(addr, gd5429) | (gd5429_read_linear(addr+1, gd5429) << 8) |
+ (gd5429_read_linear(addr+2, gd5429) << 16) | (gd5429_read_linear(addr+3, gd5429) << 24);
}
void gd5429_write_linear(uint32_t addr, uint8_t val, void *p)
@@ -679,7 +836,7 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p)
gd5429_t *gd5429 = (gd5429_t *)p;
svga_t *svga = &gd5429->svga;
uint8_t vala, valb, valc, vald, wm = svga->writemask;
- int writemask2 = svga->writemask;
+ int writemask2 = svga->seqregs[2];
cycles -= video_timing_write_b;
cycles_lost += video_timing_write_b;
@@ -689,11 +846,20 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p)
// if (svga_output) pclog("Write LFB %08X %02X ", addr, val);
if (!(svga->gdcreg[6] & 1))
svga->fullchange = 2;
- if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4))
+ if (svga->gdcreg[0xb] & GRB_ENHANCED_16BIT)
+ addr <<= 4;
+ else if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING)
+ addr <<= 3;
+ else if (((svga->chain4 && svga->packed_chain4) || svga->fb_only) && (svga->writemode < 4))
{
writemask2 = 1 << (addr & 3);
addr &= ~3;
}
+ else if (svga->chain4)
+ {
+ writemask2 = 1 << (addr & 3);
+ addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
+ }
else if (svga->chain2_write)
{
writemask2 &= ~0xa;
@@ -716,10 +882,9 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p)
switch (svga->writemode)
{
case 4:
- if (svga->gdcreg[0xb] & 0x10)
+ if (svga->gdcreg[0xb] & GRB_ENHANCED_16BIT)
{
// pclog("Writemode 4 : %X ", addr);
- addr <<= 2;
svga->changedvram[addr >> 12] = changeframecount;
// pclog("%X %X %02x\n", addr, val, svga->gdcreg[0xb]);
if (val & svga->seqregs[2] & 0x80)
@@ -766,7 +931,6 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p)
else
{
// pclog("Writemode 4 : %X ", addr);
- addr <<= 1;
svga->changedvram[addr >> 12] = changeframecount;
// pclog("%X %X %02x\n", addr, val, svga->gdcreg[0xb]);
if (val & svga->seqregs[2] & 0x80)
@@ -789,10 +953,9 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p)
break;
case 5:
- if (svga->gdcreg[0xb] & 0x10)
+ if (svga->gdcreg[0xb] & GRB_ENHANCED_16BIT)
{
// pclog("Writemode 5 : %X ", addr);
- addr <<= 2;
svga->changedvram[addr >> 12] = changeframecount;
// pclog("%X %X %02x\n", addr, val, svga->gdcreg[0xb]);
if (svga->seqregs[2] & 0x80)
@@ -839,7 +1002,6 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p)
else
{
// pclog("Writemode 5 : %X ", addr);
- addr <<= 1;
svga->changedvram[addr >> 12] = changeframecount;
// pclog("%X %X %02x\n", addr, val, svga->gdcreg[0xb]);
if (svga->seqregs[2] & 0x80)
@@ -862,10 +1024,27 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p)
break;
case 1:
- if (writemask2 & 1) svga->vram[addr] = svga->la;
- if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb;
- if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc;
- if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld;
+ if (svga->gdcreg[0xb] & GRB_WRITEMODE_EXT)
+ {
+ if (writemask2 & 0x80) svga->vram[addr] = svga->la;
+ if (writemask2 & 0x40) svga->vram[addr | 0x1] = svga->lb;
+ if (writemask2 & 0x20) svga->vram[addr | 0x2] = svga->lc;
+ if (writemask2 & 0x10) svga->vram[addr | 0x3] = svga->ld;
+ if (svga->gdcreg[0xb] & GRB_8B_LATCHES)
+ {
+ if (writemask2 & 0x08) svga->vram[addr | 0x4] = gd5429->latch_ext[0];
+ if (writemask2 & 0x04) svga->vram[addr | 0x5] = gd5429->latch_ext[1];
+ if (writemask2 & 0x02) svga->vram[addr | 0x6] = gd5429->latch_ext[2];
+ if (writemask2 & 0x01) svga->vram[addr | 0x7] = gd5429->latch_ext[3];
+ }
+ }
+ else
+ {
+ if (writemask2 & 1) svga->vram[addr] = svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld;
+ }
break;
case 0:
if (svga->gdcreg[3] & 7)
@@ -1003,24 +1182,116 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p)
}
}
+uint8_t gd5429_read_linear(uint32_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+ uint8_t temp, temp2, temp3, temp4;
+ int readplane = svga->readplane;
+ uint32_t latch_addr;
+
+ cycles -= video_timing_read_b;
+ cycles_lost += video_timing_read_b;
+
+ egareads++;
+
+ if (svga->gdcreg[0xb] & GRB_ENHANCED_16BIT)
+ latch_addr = (addr << 4) & svga->decode_mask;
+ else if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING)
+ latch_addr = (addr << 3) & svga->decode_mask;
+ else
+ latch_addr = (addr << 2) & svga->decode_mask;
+
+ if (svga->gdcreg[0xb] & GRB_ENHANCED_16BIT)
+ addr <<= 4;
+ else if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING)
+ addr <<= 3;
+ else if ((svga->chain4 && svga->packed_chain4) || svga->fb_only)
+ {
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return 0xff;
+ return svga->vram[addr & svga->vram_mask];
+ }
+ else if (svga->chain4)
+ {
+ readplane = addr & 3;
+ addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
+ }
+ else if (svga->chain2_read)
+ {
+ readplane = (readplane & 2) | (addr & 1);
+ addr &= ~1;
+ addr <<= 2;
+ }
+ else
+ addr<<=2;
+
+ addr &= svga->decode_mask;
+
+ if (latch_addr >= svga->vram_max)
+ {
+ svga->la = svga->lb = svga->lc = svga->ld = 0xff;
+ if (svga->gdcreg[0xb] & GRB_8B_LATCHES)
+ gd5429->latch_ext[0] = gd5429->latch_ext[1] = gd5429->latch_ext[2] = gd5429->latch_ext[3] = 0xff;
+ }
+ else
+ {
+ latch_addr &= svga->vram_mask;
+ svga->la = svga->vram[latch_addr];
+ svga->lb = svga->vram[latch_addr | 0x1];
+ svga->lc = svga->vram[latch_addr | 0x2];
+ svga->ld = svga->vram[latch_addr | 0x3];
+ if (svga->gdcreg[0xb] & GRB_8B_LATCHES)
+ {
+ gd5429->latch_ext[0] = svga->vram[latch_addr | 0x4];
+ gd5429->latch_ext[1] = svga->vram[latch_addr | 0x5];
+ gd5429->latch_ext[2] = svga->vram[latch_addr | 0x6];
+ gd5429->latch_ext[3] = svga->vram[latch_addr | 0x7];
+ }
+ }
+
+ if (addr >= svga->vram_max)
+ return 0xff;
+
+ addr &= svga->vram_mask;
+
+ if (svga->readmode)
+ {
+ temp = svga->la;
+ temp ^= (svga->colourcompare & 1) ? 0xff : 0;
+ temp &= (svga->colournocare & 1) ? 0xff : 0;
+ temp2 = svga->lb;
+ temp2 ^= (svga->colourcompare & 2) ? 0xff : 0;
+ temp2 &= (svga->colournocare & 2) ? 0xff : 0;
+ temp3 = svga->lc;
+ temp3 ^= (svga->colourcompare & 4) ? 0xff : 0;
+ temp3 &= (svga->colournocare & 4) ? 0xff : 0;
+ temp4 = svga->ld;
+ temp4 ^= (svga->colourcompare & 8) ? 0xff : 0;
+ temp4 &= (svga->colournocare & 8) ? 0xff : 0;
+ return ~(temp | temp2 | temp3 | temp4);
+ }
+//printf("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane);
+ return svga->vram[addr | readplane];
+}
+
static void gd5429_writeb_linear(uint32_t addr, uint8_t val, void *p)
{
- svga_t *svga = (svga_t *)p;
- gd5429_t *gd5429 = (gd5429_t *)svga->p;
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
-// pclog("gd5429_writeb : %08X %02X\n", addr, val);
- if (svga->writemode < 4)
+ if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
svga_write_linear(addr, val, svga);
else
gd5429_write_linear(addr, val & 0xff, gd5429);
}
static void gd5429_writew_linear(uint32_t addr, uint16_t val, void *p)
{
- svga_t *svga = (svga_t *)p;
- gd5429_t *gd5429 = (gd5429_t *)svga->p;
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
-// pclog("gd5429_writew : %08X %04X\n", addr, val);
- if (svga->writemode < 4)
+ if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
svga_writew_linear(addr, val, svga);
else
{
@@ -1030,11 +1301,10 @@ static void gd5429_writew_linear(uint32_t addr, uint16_t val, void *p)
}
static void gd5429_writel_linear(uint32_t addr, uint32_t val, void *p)
{
- svga_t *svga = (svga_t *)p;
- gd5429_t *gd5429 = (gd5429_t *)svga->p;
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
-// pclog("gd5429_writel : %08X %08X %i\n", addr, val, svga->writemode);
- if (svga->writemode < 4)
+ if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
svga_writel_linear(addr, val, svga);
else
{
@@ -1044,7 +1314,36 @@ static void gd5429_writel_linear(uint32_t addr, uint32_t val, void *p)
gd5429_write_linear(addr+3, val >> 24, gd5429);
}
}
-
+
+static uint8_t gd5429_readb_linear(uint32_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ return svga_read_linear(addr, &gd5429->svga);
+ return gd5429_read_linear(addr, gd5429);
+}
+static uint16_t gd5429_readw_linear(uint32_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ return svga_readw_linear(addr, &gd5429->svga);
+ return gd5429_read_linear(addr, gd5429) | (gd5429_read_linear(addr+1, gd5429) << 8);
+}
+static uint32_t gd5429_readl_linear(uint32_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ return svga_readl_linear(addr, &gd5429->svga);
+ return gd5429_read_linear(addr, gd5429) | (gd5429_read_linear(addr+1, gd5429) << 8) |
+ (gd5429_read_linear(addr+2, gd5429) << 16) | (gd5429_read_linear(addr+3, gd5429) << 24);
+}
+
void gd5429_start_blit(uint32_t cpu_dat, int count, void *p)
{
@@ -1101,15 +1400,9 @@ void gd5429_start_blit(uint32_t cpu_dat, int count, void *p)
else
{
if (!(svga->seqregs[7] & 0xf0))
- {
mem_mapping_set_handler(&svga->mapping, gd5429_read, gd5429_readw, gd5429_readl, gd5429_write, gd5429_writew, gd5429_writel);
- mem_mapping_set_p(&svga->mapping, gd5429);
- }
else
- {
- mem_mapping_set_handler(&gd5429->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, gd5429_writeb_linear, gd5429_writew_linear, gd5429_writel_linear);
- mem_mapping_set_p(&gd5429->linear_mapping, svga);
- }
+ mem_mapping_set_handler(&gd5429->linear_mapping, gd5429_readb_linear, gd5429_readw_linear, gd5429_readl_linear, gd5429_writeb_linear, gd5429_writew_linear, gd5429_writel_linear);
gd5429_recalc_mapping(gd5429);
}
}
@@ -1254,9 +1547,18 @@ void gd5429_start_blit(uint32_t cpu_dat, int count, void *p)
}
//pclog("%02X %02X\n", dst, mask);
- if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
- !((gd5429->blt.mode & 0x08) && !mask))
- svga->vram[gd5429->blt.dst_addr & svga->vram_mask] = dst;
+ if (gd5429->type <= CL_TYPE_GD5428)
+ {
+ if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
+ (!(gd5429->blt.mode & 0x08) || (dst & gd5429->blt.trans_mask) != gd5429->blt.trans_col))
+ svga->vram[gd5429->blt.dst_addr & svga->vram_mask] = dst;
+ }
+ else
+ {
+ if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
+ !((gd5429->blt.mode & 0x08) && !mask))
+ svga->vram[gd5429->blt.dst_addr & svga->vram_mask] = dst;
+ }
gd5429->blt.dst_addr += ((gd5429->blt.mode & 0x01) ? -1 : 1);
@@ -1299,15 +1601,9 @@ void gd5429_start_blit(uint32_t cpu_dat, int count, void *p)
if (gd5429->blt.mode & 0x04)
{
if (!(svga->seqregs[7] & 0xf0))
- {
mem_mapping_set_handler(&svga->mapping, gd5429_read, gd5429_readw, gd5429_readl, gd5429_write, gd5429_writew, gd5429_writel);
- mem_mapping_set_p(&svga->mapping, gd5429);
- }
else
- {
- mem_mapping_set_handler(&gd5429->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, gd5429_writeb_linear, gd5429_writew_linear, gd5429_writel_linear);
- mem_mapping_set_p(&gd5429->linear_mapping, svga);
- }
+ mem_mapping_set_handler(&gd5429->linear_mapping, gd5429_readb_linear, gd5429_readw_linear, gd5429_readl_linear, gd5429_writeb_linear, gd5429_writew_linear, gd5429_writel_linear);
// mem_mapping_set_handler(&gd5429->svga.mapping, gd5429_read, NULL, NULL, gd5429_write, NULL, NULL);
// mem_mapping_set_p(&gd5429->svga.mapping, gd5429);
gd5429_recalc_mapping(gd5429);
@@ -1520,14 +1816,22 @@ static uint32_t gd5429_mmio_readl(uint32_t addr, void *p)
void gd5429_blt_write_w(uint32_t addr, uint16_t val, void *p)
{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
// pclog("gd5429_blt_write_w %08X %08X\n", addr, val);
- gd5429_start_blit(val, 16, p);
+ if (!gd5429->blt.mem_word_sel)
+ gd5429->blt.mem_word_save = val;
+ else
+ gd5429_start_blit(gd5429->blt.mem_word_save | (val << 16), 32, p);
+ gd5429->blt.mem_word_sel = !gd5429->blt.mem_word_sel;
+
}
void gd5429_blt_write_l(uint32_t addr, uint32_t val, void *p)
{
gd5429_t *gd5429 = (gd5429_t *)p;
-
+
+ gd5429->blt.mem_word_sel = 0;
// pclog("gd5429_blt_write_l %08X %08X %04X %04X\n", addr, val, ((val >> 8) & 0x00ff) | ((val << 8) & 0xff00), ((val >> 24) & 0x00ff) | ((val >> 8) & 0xff00));
if ((gd5429->blt.mode & 0x84) == 0x84)
{
@@ -1540,6 +1844,78 @@ void gd5429_blt_write_l(uint32_t addr, uint32_t val, void *p)
gd5429_start_blit(val, 32, p);
}
+uint8_t ibm_gd5428_mca_read(int port, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+// pclog("gd5429_pro_mcv_read: port=%04x %02x %04x:%04x\n", port, gd5429->pos_regs[port & 7], CS, cpu_state.pc);
+
+ return gd5429->pos_regs[port & 7];
+}
+
+static void ibm_gd5428_mapping_update(gd5429_t *gd5429)
+{
+ gd5429_recalc_mapping(gd5429);
+
+ io_removehandler(0x03a0, 0x0023, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ io_removehandler(0x03c4, 0x001c, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ if ((gd5429->pos_regs[2] & 0x01) && gd5429->vidsys_ena)
+ {
+// pclog(" GD5429 enable registers\n");
+ io_sethandler(0x03c0, 0x0003, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ io_sethandler(0x03c4, 0x001c, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ if (!(gd5429->svga.miscout & 1))
+ io_sethandler(0x03a0, 0x0020, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ gd5429->svga.override = 0;
+ if (mb_vga)
+ svga_set_override(mb_vga, 1);
+ }
+ else
+ {
+// pclog(" GD5429 disable registers\n");
+ gd5429->svga.override = 1;
+ if (mb_vga)
+ svga_set_override(mb_vga, 0);
+ }
+}
+
+void ibm_gd5428_mca_write(int port, uint8_t val, void *p)
+{
+// svga_set_override(voodoo->svga, val & 1);
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+// pclog("gd5429_pro_mcv_write: port=%04x val=%02x\n", port, val);
+
+ if (port < 0x102)
+ return;
+ gd5429->pos_regs[port & 7] = val;
+
+ if ((port & 7) == 2)
+ {
+ mem_mapping_disable(&gd5429->bios_rom.mapping);
+ io_removehandler(0x03c3, 0x0001, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ if (gd5429->pos_regs[2] & 0x01)
+ {
+// pclog("Enable BIOS mapping\n");
+ mem_mapping_enable(&gd5429->bios_rom.mapping);
+ io_sethandler(0x03c3, 0x0001, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ }
+// else
+// pclog("Disable BIOS mapping\n");
+ }
+
+ ibm_gd5428_mapping_update(gd5429);
+}
+
+static void ibm_gd5428_mca_reset(void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+// pclog("ibm_gd5428_mca_reset\n");
+ gd5429->vidsys_ena = 0;
+ ibm_gd5428_mca_write(0x102, 0, gd5429);
+}
+
static uint8_t cl_pci_read(int func, int addr, void *p)
{
gd5429_t *gd5429 = (gd5429_t *)p;
@@ -1625,21 +2001,28 @@ static void cl_pci_write(int func, int addr, uint8_t val, void *p)
}
}
-static void *cl_init(int type, char *fn, int pci_card)
+static void *cl_init(int type, char *fn, int pci_card, uint32_t force_vram_size)
{
gd5429_t *gd5429 = malloc(sizeof(gd5429_t));
svga_t *svga = &gd5429->svga;
int vram_size;
memset(gd5429, 0, sizeof(gd5429_t));
- vram_size = device_get_config_int("memory");
- gd5429->vram_mask = (vram_size << 20) - 1;
+ if (force_vram_size)
+ vram_size = force_vram_size;
+ else
+ vram_size = device_get_config_int("memory");
+ if (vram_size >= 256)
+ gd5429->vram_mask = (vram_size << 10) - 1;
+ else
+ gd5429->vram_mask = (vram_size << 20) - 1;
gd5429->type = type;
- rom_init(&gd5429->bios_rom, fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
+ if (fn)
+ rom_init(&gd5429->bios_rom, fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
- svga_init(&gd5429->svga, gd5429, vram_size << 20,
+ svga_init(&gd5429->svga, gd5429, (vram_size >= 256) ? (vram_size << 10) : (vram_size << 20),
gd5429_recalctimings,
gd5429_in, gd5429_out,
gd5429_hwcursor_draw,
@@ -1649,9 +2032,15 @@ static void *cl_init(int type, char *fn, int pci_card)
mem_mapping_set_p(&gd5429->svga.mapping, gd5429);
mem_mapping_add(&gd5429->mmio_mapping, 0, 0, gd5429_mmio_read, gd5429_mmio_readw, gd5429_mmio_readl, gd5429_mmio_write, gd5429_mmio_writew, gd5429_mmio_writel, NULL, 0, gd5429);
- mem_mapping_add(&gd5429->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, gd5429_writeb_linear, gd5429_writew_linear, gd5429_writel_linear, NULL, 0, svga);
+ mem_mapping_add(&gd5429->linear_mapping, 0, 0, gd5429_readb_linear, gd5429_readw_linear, gd5429_readl_linear, gd5429_writeb_linear, gd5429_writew_linear, gd5429_writel_linear, NULL, 0, gd5429);
io_sethandler(0x03c0, 0x0020, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ if (type == CL_TYPE_AVGA2)
+ {
+ io_sethandler(0x0102, 0x0001, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ io_sethandler(0x46e8, 0x0002, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ svga->decode_mask = svga->vram_mask;
+ }
svga->hwcursor.yoff = 32;
svga->hwcursor.xoff = 0;
@@ -1689,27 +2078,76 @@ static void *cl_init(int type, char *fn, int pci_card)
}
+static void *avga2_init()
+{
+ return cl_init(CL_TYPE_AVGA2, "avga2vram.vbi", -1, 0);
+}
+static void *avga2_cbm_sl386sx_init()
+{
+ return cl_init(CL_TYPE_AVGA2, "cbm_sl386sx25/c000.rom", -1, 0);
+}
+static void *gd5426_ps1_init()
+{
+ return cl_init(CL_TYPE_GD5426, NULL, -1, 1);
+}
+static void *gd5428_init()
+{
+ return cl_init(CL_TYPE_GD5428, "Machspeed_VGA_GUI_2100_VLB.vbi", -1, 0);
+}
+static void *ibm_gd5428_init()
+{
+ gd5429_t *gd5429;
+ svga_t *mb_vga = svga_get_pri();
+
+ gd5429 = cl_init(CL_TYPE_GD5428, "SVGA141.ROM", -1, 1); /*Only supports 1MB*/
+ gd5429->mb_vga = mb_vga;
+
+ mca_add(ibm_gd5428_mca_read, ibm_gd5428_mca_write, ibm_gd5428_mca_reset, gd5429);
+ gd5429->pos_regs[0] = 0x7b;
+ gd5429->pos_regs[1] = 0x91;
+ gd5429->pos_regs[2] = 0;
+
+ gd5429_recalc_mapping(gd5429);
+ io_removehandler(0x03a0, 0x0040, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ gd5429->svga.override = 1;
+ mem_mapping_disable(&gd5429->bios_rom.mapping);
+ io_sethandler(0x46e8, 0x0001, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+
+ return gd5429;
+}
static void *gd5429_init()
{
- return cl_init(CL_TYPE_GD5429, "5429.vbi", -1);
+ return cl_init(CL_TYPE_GD5429, "5429.vbi", -1, 0);
}
static void *gd5430_init()
{
- return cl_init(CL_TYPE_GD5430, "gd5430/pci.bin", -1);
+ return cl_init(CL_TYPE_GD5430, "gd5430/pci.bin", -1, 0);
}
static void *gd5430_pb570_init()
{
- return cl_init(CL_TYPE_GD5430, "pb570/gd5430.bin", 8);
+ return cl_init(CL_TYPE_GD5430, "pb570/gd5430.bin", 8, 0);
}
static void *gd5434_init()
{
- return cl_init(CL_TYPE_GD5434, "gd5434.bin", -1);
+ return cl_init(CL_TYPE_GD5434, "gd5434.bin", -1, 0);
}
static void *gd5434_pb520r_init()
{
- return cl_init(CL_TYPE_GD5434, "pb520r/gd5434.bin", 3);
+ return cl_init(CL_TYPE_GD5434, "pb520r/gd5434.bin", 3, 0);
}
+static int avga2_available()
+{
+ return rom_present("avga2vram.vbi");
+}
+static int gd5428_available()
+{
+ return rom_present("Machspeed_VGA_GUI_2100_VLB.vbi");
+}
+static int ibm_gd5428_available()
+{
+ return rom_present(/*"FILE.ROM"*/"SVGA141.ROM");
+}
static int gd5429_available()
{
return rom_present("5429.vbi");
@@ -1753,6 +2191,33 @@ void gd5429_add_status_info(char *s, int max_len, void *p)
svga_add_status_info(s, max_len, &gd5429->svga);
}
+static device_config_t avga2_config[] =
+{
+ {
+ .name = "memory",
+ .description = "Memory size",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "256 kB",
+ .value = 256
+ },
+ {
+ .description = "512 kB",
+ .value = 512
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 512
+ },
+ {
+ .type = -1
+ }
+};
+
static device_config_t gd5429_config[] =
{
{
@@ -1806,6 +2271,71 @@ static device_config_t gd5434_config[] =
}
};
+device_t avga2_device =
+{
+ "AVGA2 / Cirrus Logic GD5402",
+ 0,
+ avga2_init,
+ gd5429_close,
+ avga2_available,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ avga2_config
+};
+
+device_t avga2_cbm_sl386sx_device =
+{
+ "AVGA2 (Commodore SL386SX-25)",
+ 0,
+ avga2_cbm_sl386sx_init,
+ gd5429_close,
+ gd5430_available,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ avga2_config
+};
+
+device_t gd5426_ps1_device =
+{
+ "Cirrus Logic GD5426 (IBM PS/1)",
+ 0,
+ gd5426_ps1_init,
+ gd5429_close,
+ NULL,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ NULL
+};
+
+device_t gd5428_device =
+{
+ "Cirrus Logic GD5428",
+ 0,
+ gd5428_init,
+ gd5429_close,
+ gd5428_available,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ gd5429_config
+};
+
+device_t ibm_gd5428_device =
+{
+ "IBM 1MB SVGA Adapter/A (Cirrus Logic GD5428)",
+ DEVICE_MCA,
+ ibm_gd5428_init,
+ gd5429_close,
+ ibm_gd5428_available,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ NULL
+};
+
device_t gd5429_device =
{
"Cirrus Logic GD5429",
diff --git a/src/vid_cl5429.h b/src/vid_cl5429.h
index a045e6e..edeab65 100644
--- a/src/vid_cl5429.h
+++ b/src/vid_cl5429.h
@@ -1,4 +1,10 @@
+extern device_t avga2_device;
+extern device_t avga2_cbm_sl386sx_device;
+extern device_t gd5426_ps1_device;
+extern device_t gd5428_device;
+extern device_t ibm_gd5428_device;
extern device_t gd5429_device;
+extern device_t gd5429_reply_m25_device;
extern device_t gd5430_device;
extern device_t gd5430_pb570_device;
extern device_t gd5434_device;
diff --git a/src/vid_ddc.c b/src/vid_ddc.c
new file mode 100644
index 0000000..9ccc7ca
--- /dev/null
+++ b/src/vid_ddc.c
@@ -0,0 +1,310 @@
+#include "ibm.h"
+#include "vid_ddc.h"
+#include "x86.h"
+
+static uint8_t edid_data[128] =
+{
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, /*Fixed header pattern*/
+ 0x65, 0x40, /*Manufacturer "PCE" - apparently unassigned by UEFI*/
+ 0x00, 0x00, /*Product code*/
+ 0x12, 0x34, 0x56, 0x78, /*Serial number*/
+ 0x01, 9, /*Manufacturer week and year*/
+ 0x01, 0x03, /*EDID version (1.3)*/
+
+ 0x08, /*Analogue input, separate sync*/
+ 34, 0, /*Landscape, 4:3*/
+ 0, /*Gamma*/
+ 0x08, /*RGB colour*/
+ 0x81, 0xf1, 0xa3, 0x57, 0x53, 0x9f, 0x27, 0x0a, 0x50, /*Chromaticity*/
+
+ 0xff, 0xff, 0xff, /*Established timing bitmap*/
+ 0x00, 0x00, /*Standard timing information*/
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+
+ /*Detailed mode descriptions*/
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, /*No extensions*/
+ 0x00
+};
+
+/*This should probably be split off into a separate I2C module*/
+enum
+{
+ TRANSMITTER_MONITOR = 1,
+ TRANSMITTER_HOST = -1
+};
+
+enum
+{
+ I2C_IDLE = 0,
+ I2C_RECEIVE,
+ I2C_RECEIVE_WAIT,
+ I2C_TRANSMIT_START,
+ I2C_TRANSMIT,
+ I2C_ACKNOWLEDGE,
+ I2C_TRANSACKNOWLEDGE,
+ I2C_TRANSMIT_WAIT
+};
+
+enum
+{
+ PROM_IDLE = 0,
+ PROM_RECEIVEADDR,
+ PROM_RECEIVEDATA,
+ PROM_SENDDATA,
+ PROM_INVALID
+};
+
+static struct
+{
+ int clock, data;
+ int state;
+ int last_data;
+ int pos;
+ int transmit;
+ uint8_t byte;
+} i2c;
+
+static struct
+{
+ int state;
+ int addr;
+ int rw;
+} prom;
+
+static void prom_stop(void)
+{
+// pclog("prom_stop()\n");
+ prom.state = PROM_IDLE;
+ i2c.transmit = TRANSMITTER_HOST;
+}
+
+static void prom_next_byte(void)
+{
+// pclog("prom_next_byte(%d)\n", prom.addr);
+ i2c.byte = edid_data[(prom.addr++) & 0x7F];
+}
+
+static void prom_write(uint8_t byte)
+{
+// pclog("prom_write: byte=%02x\n", byte);
+ switch (prom.state)
+ {
+ case PROM_IDLE:
+ if ((byte & 0xfe) != 0xa0)
+ {
+// pclog("I2C address not PROM\n");
+ prom.state = PROM_INVALID;
+ break;
+ }
+ prom.rw = byte & 1;
+ if (prom.rw)
+ {
+ prom.state = PROM_SENDDATA;
+ i2c.transmit = TRANSMITTER_MONITOR;
+ i2c.byte = edid_data[(prom.addr++) & 0x7F];
+// pclog("PROM - %02X from %02X\n",i2c.byte, prom.addr-1);
+// pclog("Transmitter now PROM\n");
+ }
+ else
+ {
+ prom.state = PROM_RECEIVEADDR;
+ i2c.transmit = TRANSMITTER_HOST;
+ }
+// pclog("PROM R/W=%i\n",promrw);
+ return;
+
+ case PROM_RECEIVEADDR:
+// pclog("PROM addr=%02X\n",byte);
+ prom.addr = byte;
+ if (prom.rw)
+ prom.state = PROM_SENDDATA;
+ else
+ prom.state = PROM_RECEIVEDATA;
+ break;
+
+ case PROM_RECEIVEDATA:
+// pclog("PROM write %02X %02X\n",promaddr,byte);
+ break;
+
+ case PROM_SENDDATA:
+ break;
+ }
+}
+
+void ddc_i2c_change(int new_clock, int new_data)
+{
+// pclog("I2C update clock %i->%i data %i->%i state %i\n",i2c.clock,new_clock,i2c.last_data,new_data,i2c.state);
+ switch (i2c.state)
+ {
+ case I2C_IDLE:
+ if (i2c.clock && new_clock)
+ {
+ if (i2c.last_data && !new_data) /*Start bit*/
+ {
+// pclog("Start bit received\n");
+ i2c.state = I2C_RECEIVE;
+ i2c.pos = 0;
+ }
+ }
+ break;
+
+ case I2C_RECEIVE_WAIT:
+ if (!i2c.clock && new_clock)
+ i2c.state = I2C_RECEIVE;
+ case I2C_RECEIVE:
+ if (!i2c.clock && new_clock)
+ {
+ i2c.byte <<= 1;
+ if (new_data)
+ i2c.byte |= 1;
+ else
+ i2c.byte &= 0xFE;
+ i2c.pos++;
+ if (i2c.pos == 8)
+ {
+ prom_write(i2c.byte);
+ i2c.state = I2C_ACKNOWLEDGE;
+ }
+ }
+ else if (i2c.clock && new_clock && new_data && !i2c.last_data) /*Stop bit*/
+ {
+// pclog("Stop bit received\n");
+ i2c.state = I2C_IDLE;
+ prom_stop();
+ }
+ else if (i2c.clock && new_clock && !new_data && i2c.last_data) /*Start bit*/
+ {
+// pclog("Start bit received\n");
+ i2c.pos = 0;
+ prom.state = PROM_IDLE;
+ }
+ break;
+
+ case I2C_ACKNOWLEDGE:
+ if (!i2c.clock && new_clock)
+ {
+// pclog("Acknowledging transfer\n");
+ new_data = 0;
+ i2c.pos = 0;
+ if (i2c.transmit == TRANSMITTER_HOST)
+ i2c.state = I2C_RECEIVE_WAIT;
+ else
+ i2c.state = I2C_TRANSMIT;
+ }
+ break;
+
+ case I2C_TRANSACKNOWLEDGE:
+ if (!i2c.clock && new_clock)
+ {
+ if (new_data) /*It's not acknowledged - must be end of transfer*/
+ {
+// pclog("End of transfer\n");
+ i2c.state = I2C_IDLE;
+ prom_stop();
+ }
+ else /*Next byte to transfer*/
+ {
+ i2c.state = I2C_TRANSMIT_START;
+ prom_next_byte();
+ i2c.pos = 0;
+// pclog("Next byte - %02X\n",i2c.byte);
+ }
+ }
+ break;
+
+ case I2C_TRANSMIT_WAIT:
+ if (i2c.clock && new_clock)
+ {
+ if (i2c.last_data && !new_data) /*Start bit*/
+ {
+ prom_next_byte();
+ i2c.pos = 0;
+// pclog("Next byte - %02X\n",i2c.byte);
+ }
+ if (!i2c.last_data && new_data) /*Stop bit*/
+ {
+// pclog("Stop bit received\n");
+ i2c.state = I2C_IDLE;
+ prom_stop();
+ }
+ }
+ break;
+
+ case I2C_TRANSMIT_START:
+ if (!i2c.clock && new_clock)
+ i2c.state = I2C_TRANSMIT;
+ if (i2c.clock && new_clock && !i2c.last_data && new_data) /*Stop bit*/
+ {
+// pclog("Stop bit received\n");
+ i2c.state = I2C_IDLE;
+ prom_stop();
+ }
+ case I2C_TRANSMIT:
+ if (!i2c.clock && new_clock)
+ {
+ i2c.clock = new_clock;
+// if (!i2c.pos)
+// pclog("Transmit byte %02x\n", i2c.byte);
+ i2c.data = new_data = i2c.byte & 0x80;
+// pclog("Transmit bit %i %i\n", i2c.byte, i2c.pos);
+ i2c.byte <<= 1;
+ i2c.pos++;
+ return;
+ }
+ if (i2c.clock && !new_clock && i2c.pos == 8)
+ {
+ i2c.state = I2C_TRANSACKNOWLEDGE;
+// pclog("Acknowledge mode\n");
+ }
+ break;
+
+ }
+ if (!i2c.clock && new_clock)
+ i2c.data = new_data;
+ i2c.last_data = new_data;
+ i2c.clock = new_clock;
+}
+
+int ddc_read_clock(void)
+{
+ return i2c.clock;
+}
+int ddc_read_data(void)
+{
+ if (i2c.state == I2C_TRANSMIT || i2c.state == I2C_ACKNOWLEDGE)
+ return i2c.data;
+ if (i2c.state == I2C_RECEIVE_WAIT)
+ return 0; /*ACK*/
+ return 1;
+}
+
+void ddc_init(void)
+{
+ int c;
+ uint8_t checksum = 0;
+
+ for (c = 0; c < 127; c++)
+ checksum += edid_data[c];
+ edid_data[127] = 256 - checksum;
+
+ i2c.clock = 1;
+ i2c.data = 1;
+}
diff --git a/src/vid_ddc.h b/src/vid_ddc.h
new file mode 100644
index 0000000..7b8f8bd
--- /dev/null
+++ b/src/vid_ddc.h
@@ -0,0 +1,4 @@
+void ddc_init(void);
+void ddc_i2c_change(int new_clock, int new_data);
+int ddc_read_clock(void);
+int ddc_read_data(void);
diff --git a/src/vid_et4000.c b/src/vid_et4000.c
index f24acbc..7f366b3 100644
--- a/src/vid_et4000.c
+++ b/src/vid_et4000.c
@@ -7,6 +7,7 @@
#include "rom.h"
#include "video.h"
#include "vid_svga.h"
+#include "vid_svga_render.h"
#include "vid_unk_ramdac.h"
#include "vid_et4000.h"
@@ -19,6 +20,16 @@ typedef struct et4000_t
rom_t bios_rom;
uint8_t banking;
+ uint8_t port_22cb_val;
+ uint8_t port_32cb_val;
+ int get_korean_font_enabled;
+ int get_korean_font_index;
+ uint16_t get_korean_font_base;
+
+ uint8_t kasan_cfg_index;
+ uint8_t kasan_cfg_regs[16];
+ uint16_t kasan_access_addr;
+ uint8_t kasan_font_data[4];
} et4000_t;
static uint8_t crtc_mask[0x40] =
@@ -33,6 +44,9 @@ static uint8_t crtc_mask[0x40] =
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+void et4000_kasan_out(uint16_t addr, uint8_t val, void *p);
+uint8_t et4000_kasan_in(uint16_t addr, void *p);
+
void et4000_out(uint16_t addr, uint8_t val, void *p)
{
et4000_t *et4000 = (et4000_t *)p;
@@ -57,6 +71,21 @@ void et4000_out(uint16_t addr, uint8_t val, void *p)
et4000->banking = val;
// pclog("Banking write %08X %08X %02X\n", svga->write_bank, svga->read_bank, val);
return;
+
+ case 0x3cf:
+ if ((svga->gdcaddr & 15) == 6)
+ {
+ old = svga->gdcreg[6];
+ svga_out(addr, val, svga);
+ if ((old & 0xc) != 0 && (val & 0xc) == 0)
+ {
+ /*override mask - ET4000 supports linear 128k at A0000*/
+ svga->banked_mask = 0x1ffff;
+ }
+ return;
+ }
+ break;
+
case 0x3D4:
svga->crtcreg = val & 0x3f;
return;
@@ -81,6 +110,172 @@ void et4000_out(uint16_t addr, uint8_t val, void *p)
svga_out(addr, val, svga);
}
+void et4000k_out(uint16_t addr, uint8_t val, void *p)
+{
+ et4000_t *et4000 = (et4000_t *)p;
+
+// pclog("ET4000k out %04X %02X\n", addr, val);
+
+ switch (addr)
+ {
+ case 0x22CB:
+ et4000->port_22cb_val = (et4000->port_22cb_val & 0xF0) | (val & 0x0F);
+ et4000->get_korean_font_enabled = val & 7;
+ if (et4000->get_korean_font_enabled == 3)
+ et4000->get_korean_font_index = 0;
+ break;
+ case 0x22CF:
+ switch (et4000->get_korean_font_enabled)
+ {
+ case 1:
+ et4000->get_korean_font_base = ((val & 0x7F) << 7) | (et4000->get_korean_font_base & 0x7F);
+ break;
+ case 2:
+ et4000->get_korean_font_base = (et4000->get_korean_font_base & 0x3F80) | (val & 0x7F) | (((val ^ 0x80) & 0x80) << 8);
+ break;
+ case 3:
+ if ((et4000->port_32cb_val & 0x30) == 0x20 && (et4000->get_korean_font_base & 0x7F) > 0x20 && (et4000->get_korean_font_base & 0x7F) < 0x7F)
+ {
+ switch (et4000->get_korean_font_base & 0x3F80)
+ {
+ case 0x2480:
+ if (et4000->get_korean_font_index < 16)
+ fontdatksc5601_user[(et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index] = val;
+ else if (et4000->get_korean_font_index >= 24 && et4000->get_korean_font_index < 40)
+ fontdatksc5601_user[(et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index - 8] = val;
+ break;
+ case 0x3F00:
+ if (et4000->get_korean_font_index < 16)
+ fontdatksc5601_user[96 + (et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index] = val;
+ else if (et4000->get_korean_font_index >= 24 && et4000->get_korean_font_index < 40)
+ fontdatksc5601_user[96 + (et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index - 8] = val;
+ break;
+ }
+ et4000->get_korean_font_index++;
+ }
+ break;
+ }
+ break;
+ case 0x32CB:
+ et4000->port_32cb_val = val;
+ svga_recalctimings(&et4000->svga);
+ break;
+ default:
+ et4000_out(addr, val, p);
+ break;
+ }
+}
+
+void et4000_kasan_out(uint16_t addr, uint8_t val, void *p)
+{
+ et4000_t *et4000 = (et4000_t *)p;
+
+// pclog("ET4000k out %04X %02X\n", addr, val);
+
+
+ if(addr == 0x258)
+ {
+ //pclog("Write port %04X to %02X at %04X:%04X\n", addr, val, CS, cpu_state.oldpc);
+ et4000->kasan_cfg_index = val;
+ }
+ else if(addr == 0x259)
+ {
+ //pclog("Write port %04X to %02X at %04X:%04X\n", addr, val, CS, cpu_state.oldpc);
+ if(et4000->kasan_cfg_index >= 0xF0)
+ {
+ switch(et4000->kasan_cfg_index - 0xF0)
+ {
+ case 0:
+ if(et4000->kasan_cfg_regs[4] & 8)
+ val = (val & 0xFC) | (et4000->kasan_cfg_regs[0] & 3);
+ et4000->kasan_cfg_regs[0] = val;
+ svga_recalctimings(&et4000->svga);
+ break;
+ case 1:
+ case 2:
+ et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val;
+ io_removehandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000);
+ et4000->kasan_access_addr = (et4000->kasan_cfg_regs[2] << 8) | et4000->kasan_cfg_regs[1];
+ io_sethandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000);
+ //pclog("Set font access address to %04X\n", et4000->kasan_access_addr);
+ break;
+ case 4:
+ if(et4000->kasan_cfg_regs[0] & 0x20)
+ val |= 0x80;
+ et4000->svga.ksc5601_swap_mode = (val & 4) >> 2;
+ et4000->kasan_cfg_regs[4] = val;
+ svga_recalctimings(&et4000->svga);
+ break;
+ case 5:
+ et4000->kasan_cfg_regs[5] = val;
+ et4000->svga.ksc5601_english_font_type = 0x100 | val;
+ break;
+ case 6:
+ case 7:
+ et4000->svga.ksc5601_udc_area_msb[et4000->kasan_cfg_index - 0xF6] = val;
+ default:
+ et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val;
+ svga_recalctimings(&et4000->svga);
+ break;
+ }
+ }
+ }
+ else if(addr >= et4000->kasan_access_addr && addr < et4000->kasan_access_addr + 8)
+ {
+ switch (addr - ((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])))
+ {
+ case 0:
+ if(et4000->kasan_cfg_regs[0] & 2)
+ {
+ et4000->get_korean_font_index = ((val & 1) << 4) | ((val & 0x1E) >> 1);
+ et4000->get_korean_font_base = (et4000->get_korean_font_base & ~7) | (val >> 5);
+ }
+ break;
+ case 1:
+ if(et4000->kasan_cfg_regs[0] & 2)
+ {
+ et4000->get_korean_font_base = (et4000->get_korean_font_base & ~0x7F8) | (val << 3);
+ }
+ break;
+ case 2:
+ if(et4000->kasan_cfg_regs[0] & 2)
+ {
+ et4000->get_korean_font_base = (et4000->get_korean_font_base & ~0x7F800) | ((val & 7) << 11);
+ }
+ break;
+ case 3:
+ case 4:
+ case 5:
+ if(et4000->kasan_cfg_regs[0] & 1)
+ {
+ et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val;
+ }
+ break;
+ case 6:
+ if((et4000->kasan_cfg_regs[0] & 1) && (et4000->kasan_font_data[3] & !val & 0x80) && (et4000->get_korean_font_base & 0x7F) >= 0x20 && (et4000->get_korean_font_base & 0x7F) < 0x7F)
+ {
+ if(((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[0] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[0] & 0x80))
+ {
+ fontdatksc5601_user[(et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index] = et4000->kasan_font_data[2];
+ }
+ else if(((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[1] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[1] & 0x80))
+ {
+ fontdatksc5601_user[96 + (et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index] = et4000->kasan_font_data[2];
+ }
+ }
+ et4000->kasan_font_data[3] = val;
+ break;
+ default:
+ break;
+ }
+ //pclog("Write port %04X at %04X:%04X\n", addr, CS, cpu_state.oldpc);
+ }
+ else
+ {
+ et4000_out(addr, val, p);
+ }
+}
+
uint8_t et4000_in(uint16_t addr, void *p)
{
et4000_t *et4000 = (et4000_t *)p;
@@ -110,6 +305,113 @@ uint8_t et4000_in(uint16_t addr, void *p)
return svga_in(addr, svga);
}
+uint8_t et4000k_in(uint16_t addr, void *p)
+{
+ uint8_t val = 0xFF;
+ et4000_t *et4000 = (et4000_t *)p;
+
+// if (addr != 0x3da) pclog("IN ET4000 %04X\n", addr);
+
+ switch (addr)
+ {
+ case 0x22CB:
+ return et4000->port_22cb_val;
+ case 0x22CF:
+ val = 0;
+ switch (et4000->get_korean_font_enabled)
+ {
+ case 3:
+ if ((et4000->port_32cb_val & 0x30) == 0x30)
+ {
+ val = fontdatksc5601[et4000->get_korean_font_base][et4000->get_korean_font_index++];
+ et4000->get_korean_font_index &= 0x1F;
+ }
+ else if ((et4000->port_32cb_val & 0x30) == 0x20 && (et4000->get_korean_font_base & 0x7F) > 0x20 && (et4000->get_korean_font_base & 0x7F) < 0x7F)
+ {
+ switch (et4000->get_korean_font_base & 0x3F80)
+ {
+ case 0x2480:
+ if (et4000->get_korean_font_index < 16)
+ val = fontdatksc5601_user[(et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index];
+ else if (et4000->get_korean_font_index >= 24 && et4000->get_korean_font_index < 40)
+ val = fontdatksc5601_user[(et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index - 8];
+ break;
+ case 0x3F00:
+ if (et4000->get_korean_font_index < 16)
+ val = fontdatksc5601_user[96 + (et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index];
+ else if (et4000->get_korean_font_index >= 24 && et4000->get_korean_font_index < 40)
+ val = fontdatksc5601_user[96 + (et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index - 8];
+ break;
+ }
+ et4000->get_korean_font_index++;
+ et4000->get_korean_font_index %= 72;
+ }
+ break;
+ case 4:
+ val = 0x0F;
+ break;
+ }
+ return val;
+ case 0x32CB:
+ return et4000->port_32cb_val;
+ }
+
+ return et4000_in(addr, p);
+}
+
+uint8_t et4000_kasan_in(uint16_t addr, void *p)
+{
+ uint8_t val = 0xFF;
+ et4000_t *et4000 = (et4000_t *)p;
+
+ if(addr == 0x258)
+ {
+ //pclog("Read port %04X at %04X:%04X\n", addr, CS, cpu_state.oldpc);
+ val = et4000->kasan_cfg_index;
+ }
+ else if(addr == 0x259)
+ {
+ //pclog("Read port %04X at %04X:%04X\n", addr, CS, cpu_state.oldpc);
+ if (et4000->kasan_cfg_index >= 0xF0)
+ {
+ val = et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0];
+ if(et4000->kasan_cfg_index == 0xF4 && et4000->kasan_cfg_regs[0] & 0x20)
+ val |= 0x80;
+ }
+ }
+ else if(addr >= et4000->kasan_access_addr && addr < et4000->kasan_access_addr + 8)
+ {
+ switch (addr - ((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])))
+ {
+ case 2:
+ val = 0;
+ break;
+ case 5:
+ if(((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[0] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[0] & 0x80))
+ {
+ val = fontdatksc5601_user[(et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index];
+ }
+ else if(((et4000->get_korean_font_base >> 7) & 0x7F) == (et4000->svga.ksc5601_udc_area_msb[1] & 0x7F) && (et4000->svga.ksc5601_udc_area_msb[1] & 0x80))
+ {
+ val = fontdatksc5601_user[96 + (et4000->get_korean_font_base & 0x7F) - 0x20][et4000->get_korean_font_index];
+ }
+ else
+ {
+ val = fontdatksc5601[et4000->get_korean_font_base][et4000->get_korean_font_index];
+ }
+ break;
+ default:
+ break;
+ }
+ //pclog(stderr, "Read port %04X at %04X:%04X\n", addr, CS, cpu_state.oldpc);
+ }
+ else
+ {
+ val = et4000_in(addr, p);
+ }
+ return val;
+}
+
void et4000_recalctimings(svga_t *svga)
{
svga->ma_latch |= (svga->crtc[0x33]&3)<<16;
@@ -127,9 +429,9 @@ void et4000_recalctimings(svga_t *svga)
switch (((svga->miscout >> 2) & 3) | ((svga->crtc[0x34] << 1) & 4))
{
case 0: case 1: break;
- case 3: svga->clock = cpuclock / 40000000.0; break;
- case 5: svga->clock = cpuclock / 65000000.0; break;
- default: svga->clock = cpuclock / 36000000.0; break;
+ case 3: svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; break;
+ case 5: svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; break;
+ default: svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; break;
}
switch (svga->bpp)
@@ -143,6 +445,42 @@ void et4000_recalctimings(svga_t *svga)
}
}
+void et4000k_recalctimings(svga_t *svga)
+{
+ et4000_t *et4000 = (et4000_t *)svga->p;
+
+ et4000_recalctimings(svga);
+
+ if (svga->render == svga_render_text_80 && ((svga->crtc[0x37] & 0x0A) == 0x0A))
+ {
+ if(et4000->port_32cb_val & 0x80)
+ {
+ svga->ma_latch -= 2;
+ svga->ca_adj = -2;
+ }
+ if((et4000->port_32cb_val & 0xB4) == ((svga->crtc[0x37] & 3) == 2 ? 0xB4 : 0xB0))
+ {
+ svga->render = svga_render_text_80_ksc5601;
+ }
+ }
+}
+
+void et4000_kasan_recalctimings(svga_t *svga)
+{
+ et4000_t *et4000 = (et4000_t *)svga->p;
+
+ et4000_recalctimings(svga);
+
+ if (svga->render == svga_render_text_80 && (et4000->kasan_cfg_regs[0] & 8))
+ {
+ svga->ma_latch -= 3;
+ svga->ca_adj = (et4000->kasan_cfg_regs[0] >> 6) - 3;
+ svga->ksc5601_sbyte_mask = (et4000->kasan_cfg_regs[0] & 4) << 5;
+ if((et4000->kasan_cfg_regs[0] & 0x23) == 0x20 && (et4000->kasan_cfg_regs[4] & 0x80) && ((svga->crtc[0x37] & 0x0B) == 0x0A))
+ svga->render = svga_render_text_80_ksc5601;
+ }
+}
+
void *et4000_init()
{
et4000_t *et4000 = malloc(sizeof(et4000_t));
@@ -157,15 +495,106 @@ void *et4000_init()
et4000_in, et4000_out,
NULL,
NULL);
+
+ et4000->svga.packed_chain4 = 1;
return et4000;
}
+void *et4000k_init()
+{
+ et4000_t *et4000 = malloc(sizeof(et4000_t));
+ memset(et4000, 0, sizeof(et4000_t));
+
+ rom_init(&et4000->bios_rom, "tgkorvga.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
+ loadfont("tg_ksc5601.rom", 6);
+
+ io_sethandler(0x03c0, 0x0020, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000);
+
+ io_sethandler(0x22cb, 0x0001, et4000k_in, NULL, NULL, et4000k_out, NULL, NULL, et4000);
+ io_sethandler(0x22cf, 0x0001, et4000k_in, NULL, NULL, et4000k_out, NULL, NULL, et4000);
+ io_sethandler(0x32cb, 0x0001, et4000k_in, NULL, NULL, et4000k_out, NULL, NULL, et4000);
+ et4000->port_22cb_val = 0x60;
+ et4000->port_32cb_val = 0;
+
+ svga_init(&et4000->svga, et4000, 1 << 20, /*1mb*/
+ et4000k_recalctimings,
+ et4000k_in, et4000k_out,
+ NULL,
+ NULL);
+
+ et4000->svga.ksc5601_sbyte_mask = 0x80;
+ et4000->svga.ksc5601_udc_area_msb[0] = 0xC9;
+ et4000->svga.ksc5601_udc_area_msb[1] = 0xFE;
+ et4000->svga.ksc5601_swap_mode = 0;
+ et4000->svga.ksc5601_english_font_type = 0;
+
+ et4000->svga.packed_chain4 = 1;
+
+ return et4000;
+}
+
+void *et4000_kasan_init()
+{
+ int i;
+ et4000_t *et4000 = malloc(sizeof(et4000_t));
+ memset(et4000, 0, sizeof(et4000_t));
+
+ rom_init(&et4000->bios_rom, "et4000_kasan16.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
+ loadfont("kasan_ksc5601.rom", 6);
+
+ io_sethandler(0x03c0, 0x0020, et4000_in, NULL, NULL, et4000_out, NULL, NULL, et4000);
+
+ io_sethandler(0x0258, 0x0002, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000);
+
+ svga_init(&et4000->svga, et4000, 1 << 20, /*1mb*/
+ et4000_kasan_recalctimings,
+ et4000_in, et4000_out,
+ NULL,
+ NULL);
+
+ et4000->svga.ksc5601_sbyte_mask = 0;
+ et4000->kasan_cfg_index = 0;
+ for(i=0; i<16; i++)
+ et4000->kasan_cfg_regs[i] = 0;
+ for(i=0; i<4; i++)
+ et4000->kasan_font_data[i] = 0;
+ et4000->kasan_cfg_regs[1] = 0x50;
+ et4000->kasan_cfg_regs[2] = 2;
+ et4000->kasan_cfg_regs[3] = 6;
+ et4000->kasan_cfg_regs[4] = 0x78;
+ et4000->kasan_cfg_regs[5] = 0xFF;
+ et4000->kasan_cfg_regs[6] = 0xC9;
+ et4000->kasan_cfg_regs[7] = 0xFE;
+ et4000->kasan_access_addr = 0x250;
+ io_sethandler(0x250, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000);
+
+ et4000->svga.ksc5601_sbyte_mask = 0;
+ et4000->svga.ksc5601_udc_area_msb[0] = 0xC9;
+ et4000->svga.ksc5601_udc_area_msb[1] = 0xFE;
+ et4000->svga.ksc5601_swap_mode = 0;
+ et4000->svga.ksc5601_english_font_type = 0x1FF;
+
+ et4000->svga.packed_chain4 = 1;
+
+ return et4000;
+}
+
static int et4000_available()
{
return rom_present("et4000.bin");
}
+static int et4000k_available()
+{
+ return rom_present("tgkorvga.bin") && rom_present("tg_ksc5601.rom");;
+}
+
+static int et4000_kasan_available()
+{
+ return rom_present("et4000_kasan16.bin") && rom_present("kasan_ksc5601.rom");;
+}
+
void et4000_close(void *p)
{
et4000_t *et4000 = (et4000_t *)p;
@@ -207,3 +636,27 @@ device_t et4000_device =
et4000_force_redraw,
et4000_add_status_info
};
+
+device_t et4000k_device =
+{
+ "Trigem Korean VGA(Tseng Labs ET4000AX)",
+ 0,
+ et4000k_init,
+ et4000_close,
+ et4000k_available,
+ et4000_speed_changed,
+ et4000_force_redraw,
+ et4000_add_status_info
+};
+
+device_t et4000_kasan_device =
+{
+ "Kasan Hangulmadang-16(Tseng Labs ET4000AX)",
+ 0,
+ et4000_kasan_init,
+ et4000_close,
+ et4000_kasan_available,
+ et4000_speed_changed,
+ et4000_force_redraw,
+ et4000_add_status_info
+};
diff --git a/src/vid_et4000.h b/src/vid_et4000.h
index cc7e161..9d18590 100644
--- a/src/vid_et4000.h
+++ b/src/vid_et4000.h
@@ -1 +1,3 @@
extern device_t et4000_device;
+extern device_t et4000k_device;
+extern device_t et4000_kasan_device;
diff --git a/src/vid_et4000w32.c b/src/vid_et4000w32.c
index 1775977..b84cdbd 100644
--- a/src/vid_et4000w32.c
+++ b/src/vid_et4000w32.c
@@ -293,7 +293,7 @@ void et4000w32p_recalctimings(svga_t *svga)
switch ((svga->miscout >> 2) & 3)
{
case 0: case 1: break;
- case 2: case 3: svga->clock = cpuclock / icd2061_getfreq(&et4000->icd2061, 2); break;
+ case 2: case 3: svga->clock = (cpuclock * (double)(1ull << 32)) / icd2061_getfreq(&et4000->icd2061, 2); break;
}
switch (svga->bpp)
@@ -337,7 +337,7 @@ void et4000w32p_recalcmapping(et4000w32p_t *et4000)
case 0x0: case 0x4: case 0x8: case 0xC: /*128k at A0000*/
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
mem_mapping_disable(&et4000->mmu_mapping);
- svga->banked_mask = 0xffff;
+ svga->banked_mask = 0x1ffff;
break;
case 0x1: /*64k at A0000*/
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
@@ -1207,6 +1207,8 @@ void *et4000w32p_init()
et4000->fifo_not_full_event = thread_create_event();
et4000->fifo_thread = thread_create(fifo_thread, et4000);
+ et4000->svga.packed_chain4 = 1;
+
return et4000;
}
diff --git a/src/vid_genius.c b/src/vid_genius.c
index 50f2e1d..f8c3688 100644
--- a/src/vid_genius.c
+++ b/src/vid_genius.c
@@ -13,7 +13,6 @@
#define GENIUS_YSIZE 1008
void updatewindowsize(int x, int y);
-void loadfont(char *s, int format);
extern uint8_t fontdat8x12[256][16];
@@ -421,7 +420,7 @@ void genius_hiresline(genius_t *genius)
{
int x, c;
uint32_t dat;
- uint8_t ink;
+ uint32_t ink;
uint32_t addr;
ink = (genius->genius_control & 0x20) ? genius_pal[0] : genius_pal[3];
@@ -458,7 +457,7 @@ void genius_poll(void *p)
{
genius_t *genius = (genius_t *)p;
int x;
- uint8_t background;
+ uint32_t background;
if (!genius->linepos)
{
diff --git a/src/vid_ht216.c b/src/vid_ht216.c
new file mode 100644
index 0000000..aa717e4
--- /dev/null
+++ b/src/vid_ht216.c
@@ -0,0 +1,1141 @@
+#include
+#include "ibm.h"
+#include "device.h"
+#include "io.h"
+#include "mem.h"
+#include "rom.h"
+#include "video.h"
+#include "vid_ht216.h"
+#include "vid_svga.h"
+#include "vid_svga_render.h"
+#include "vid_unk_ramdac.h"
+
+typedef struct ht216_t
+{
+ svga_t svga;
+
+ mem_mapping_t linear_mapping;
+
+ rom_t bios_rom;
+
+ uint32_t vram_mask;
+
+ int ext_reg_enable;
+ int clk_sel;
+
+ uint8_t read_bank_reg[2], write_bank_reg[2];
+ uint32_t read_bank[2], write_bank[2];
+ uint8_t misc;
+
+ uint8_t bg_latch[8];
+
+ uint8_t ht_regs[256];
+} ht216_t;
+
+#define HT_MISC_PAGE_SEL (1 << 5)
+
+/*Shifts CPU VRAM read address by 3 bits, for use with fat pixel colour expansion*/
+#define HT_REG_C8_MOVSB (1 << 0)
+#define HT_REG_C8_E256 (1 << 4)
+#define HT_REG_C8_XLAM (1 << 6)
+
+#define HT_REG_CD_FP8PCEXP (1 << 1)
+#define HT_REG_CD_BMSKSL (3 << 2)
+#define HT_REG_CD_RMWMDE (1 << 5)
+/*Use GDC data rotate as offset when reading VRAM data into latches*/
+#define HT_REG_CD_ASTODE (1 << 6)
+#define HT_REG_CD_EXALU (1 << 7)
+
+#define HT_REG_E0_SBAE (1 << 7)
+
+#define HT_REG_F9_XPSEL (1 << 0)
+
+/*Enables A[14:15] of VRAM address in chain-4 modes*/
+#define HT_REG_FC_ECOLRE (1 << 2)
+
+#define HT_REG_FE_FBRC (1 << 1)
+#define HT_REG_FE_FBMC (3 << 2)
+#define HT_REG_FE_FBRSL (3 << 4)
+
+void ht216_remap(ht216_t *ht216);
+
+void ht216_out(uint16_t addr, uint8_t val, void *p);
+uint8_t ht216_in(uint16_t addr, void *p);
+
+void ht216_out(uint16_t addr, uint8_t val, void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+ svga_t *svga = &ht216->svga;
+ uint8_t old;
+
+// pclog("ht216 %i out %04X %02X %04X:%04X\n", svga->miscout & 1, addr, val, CS, cpu_state.pc);
+
+ if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
+ addr ^= 0x60;
+
+ switch (addr)
+ {
+ case 0x3c2:
+ ht216->clk_sel = (ht216->clk_sel & ~3) | ((val & 0x0c) >> 2);
+ ht216->misc = val;
+ ht216->read_bank_reg[0] = (ht216->read_bank_reg[0] & ~0x20) | ((val & HT_MISC_PAGE_SEL) ? 0x20 : 0);
+ ht216->write_bank_reg[0] = (ht216->write_bank_reg[0] & ~0x20) | ((val & HT_MISC_PAGE_SEL) ? 0x20 : 0);
+ ht216_remap(ht216);
+ svga_recalctimings(&ht216->svga);
+ break;
+
+ case 0x3c5:
+ if (svga->seqaddr == 4)
+ {
+ svga->chain4 = val & 8;
+ ht216_remap(ht216);
+ }
+ else if (svga->seqaddr == 6)
+ {
+ if (val == 0xea)
+ ht216->ext_reg_enable = 1;
+ else if (val == 0xae)
+ ht216->ext_reg_enable = 0;
+ }
+ else if (svga->seqaddr >= 0x80 && ht216->ext_reg_enable)
+ {
+ ht216->ht_regs[svga->seqaddr & 0xff] = val;
+// pclog("HT[%02x]=%02x %04x(%08x):%08x\n", svga->seqaddr, val, CS,cs,cpu_state.pc);
+ switch (svga->seqaddr & 0xff)
+ {
+ case 0x83:
+ svga->attraddr = val & 0x1f;
+ svga->attrff = (val & 0x80) ? 1 : 0;
+ break;
+
+ case 0x94:
+ svga->hwcursor.addr = ((val << 6) | (3 << 14) | ((ht216->ht_regs[0xff] & 0x60) << 11)) << 2;
+ //pclog("cursor_addr = %05x\n", svga->hwcursor.addr);
+ break;
+ case 0x9c: case 0x9d:
+ svga->hwcursor.x = ht216->ht_regs[0x9d] | ((ht216->ht_regs[0x9c] & 7) << 8);
+ break;
+ case 0x9e: case 0x9f:
+ svga->hwcursor.y = ht216->ht_regs[0x9f] | ((ht216->ht_regs[0x9e] & 3) << 8);
+ break;
+ case 0xa0:
+ svga->la = val;
+ break;
+ case 0xa1:
+ svga->lb = val;
+ break;
+ case 0xa2:
+ svga->lc = val;
+ break;
+ case 0xa3:
+ svga->ld = val;
+ break;
+ case 0xa4:
+ ht216->clk_sel = (val >> 2) & 0xf;
+ svga->miscout = (svga->miscout & ~0xc) | ((ht216->clk_sel & 3) << 2);
+ break;
+ case 0xa5:
+ svga->hwcursor.ena = val & 0x80;
+ break;
+ case 0xe8:
+ ht216->read_bank_reg[0] = val;
+ ht216->write_bank_reg[0] = val;
+ break;
+ case 0xe9:
+ ht216->read_bank_reg[1] = val;
+ ht216->write_bank_reg[1] = val;
+ break;
+ case 0xf6:
+ svga->vram_display_mask = (val & 0x40) ? ht216->vram_mask : 0x3ffff;
+ ht216->read_bank_reg[0] = (ht216->read_bank_reg[0] & ~0xc0) | ((val & 0xc) << 4);
+ ht216->write_bank_reg[0] = (ht216->write_bank_reg[0] & ~0xc0) | ((val & 0x3) << 6);
+ break;
+ case 0xf9:
+ ht216->read_bank_reg[0] = (ht216->read_bank_reg[0] & ~0x10) | ((val & 1) ? 0x10 : 0);
+ ht216->write_bank_reg[0] = (ht216->write_bank_reg[0] & ~0x10) | ((val & 1) ? 0x10 : 0);
+ break;
+ case 0xfc:
+ svga->packed_chain4 = val & 0x20;
+ break;
+ case 0xff:
+ svga->hwcursor.addr = ((ht216->ht_regs[0x94] << 6) | (3 << 14) | ((val & 0x60) << 11)) << 2;
+ //pclog("cursor_addr = %05x\n", svga->hwcursor.addr);
+ break;
+ }
+ switch (svga->seqaddr & 0xff)
+ {
+ case 0xa4: case 0xf6: case 0xfc:
+ svga->fullchange = changeframecount;
+ svga_recalctimings(&ht216->svga);
+ break;
+ }
+ switch (svga->seqaddr & 0xff)
+ {
+ case 0xc8: case 0xc9: case 0xcf:
+ case 0xe0: case 0xe8: case 0xe9:
+ case 0xf6: case 0xf9:
+ ht216_remap(ht216);
+ break;
+ }
+ return;
+ }
+ break;
+
+ case 0x3cf:
+ if (svga->gdcaddr == 6)
+ {
+ if (val & 8)
+ svga->banked_mask = 0x7fff;
+ else
+ svga->banked_mask = 0xffff;
+ }
+ break;
+
+ case 0x3D4:
+ svga->crtcreg = val & 0x3f;
+ 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);
+
+// if (svga->crtcreg == 0xc)
+// pclog("CRTC[C]=%02x %08x\n", val, svga->vram_display_mask);
+ old = svga->crtc[svga->crtcreg];
+ svga->crtc[svga->crtcreg] = val;
+
+ if (old != val)
+ {
+ if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
+ {
+ svga->fullchange = changeframecount;
+ svga_recalctimings(&ht216->svga);
+ }
+ }
+ break;
+
+ case 0x46e8:
+ io_removehandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216);
+ mem_mapping_disable(&ht216->svga.mapping);
+ mem_mapping_disable(&ht216->linear_mapping);
+ if (val & 8)
+ {
+ io_sethandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216);
+ mem_mapping_enable(&ht216->svga.mapping);
+ ht216_remap(ht216);
+ }
+ break;
+ }
+ svga_out(addr, val, svga);
+}
+
+uint8_t ht216_in(uint16_t addr, void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+ svga_t *svga = &ht216->svga;
+
+// if (addr != 0x3ba && addr != 0x3da) pclog("ht216 %i in %04X\n", svga->miscout & 1, addr);
+
+ if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
+ addr ^= 0x60;
+
+ switch (addr)
+ {
+ case 0x3c2:
+// pclog("3C2 read\n");
+ break;
+// return 0x10;
+
+ case 0x3c5:
+ if (svga->seqaddr == 6)
+ return ht216->ext_reg_enable;
+ if (svga->seqaddr >= 0x80)
+ {
+ if (ht216->ext_reg_enable)
+ {
+// pclog("Read HT[%02x]=%02x\n", svga->seqaddr & 0xff, ht216->ht_regs[svga->seqaddr & 0xff]);
+ switch (svga->seqaddr & 0xff)
+ {
+ case 0x83:
+ if (svga->attrff)
+ return svga->attraddr | 0x80;
+ return svga->attraddr;
+
+ case 0x8e: return 0x61; /*HT216-32*/
+ case 0x8f: return 0x78;
+
+ case 0xa0:
+ return svga->la;
+ case 0xa1:
+ return svga->lb;
+ case 0xa2:
+ return svga->lc;
+ case 0xa3:
+ return svga->ld;
+ }
+ return ht216->ht_regs[svga->seqaddr & 0xff];
+ }
+ else
+ return 0xff;
+ }
+ break;
+
+ case 0x3D4:
+ return svga->crtcreg;
+ case 0x3D5:
+ if (svga->crtcreg == 0x1f)
+ return svga->crtc[0xc] ^ 0xea;
+ return svga->crtc[svga->crtcreg];
+ }
+ return svga_in(addr, svga);
+}
+
+void ht216_remap(ht216_t *ht216)
+{
+ svga_t *svga = &ht216->svga;
+
+ mem_mapping_disable(&ht216->linear_mapping);
+ if (ht216->ht_regs[0xc8] & HT_REG_C8_XLAM)
+ {
+ uint32_t linear_base = ((ht216->ht_regs[0xc9] & 0xf) << 20) | (ht216->ht_regs[0xcf] << 24);
+
+ pclog("Linear base %08x\n", linear_base);
+ mem_mapping_set_addr(&ht216->linear_mapping, linear_base, 0x100000);
+
+ /*Linear mapping enabled*/
+ }
+ else
+ {
+ uint8_t read_bank_reg[2] = {ht216->read_bank_reg[0], ht216->read_bank_reg[1]};
+ uint8_t write_bank_reg[2] = {ht216->write_bank_reg[0], ht216->write_bank_reg[1]};
+
+ if (!svga->chain4 || !(ht216->ht_regs[0xfc] & HT_REG_FC_ECOLRE))
+ {
+ read_bank_reg[0] &= ~0x30;
+ read_bank_reg[1] &= ~0x30;
+ write_bank_reg[0] &= ~0x30;
+ write_bank_reg[1] &= ~0x30;
+ }
+
+ ht216->read_bank[0] = read_bank_reg[0] << 12;
+ ht216->write_bank[0] = write_bank_reg[0] << 12;
+ if (ht216->ht_regs[0xe0] & HT_REG_E0_SBAE)
+ {
+ /*Split bank*/
+ ht216->read_bank[1] = read_bank_reg[1] << 12;
+ ht216->write_bank[1] = write_bank_reg[1] << 12;
+ }
+ else
+ {
+ ht216->read_bank[1] = ht216->read_bank[0] + (svga->chain4 ? 0x8000 : 0x20000);
+ ht216->write_bank[1] = ht216->write_bank[0] + (svga->chain4 ? 0x8000 : 0x20000);
+ }
+
+ if (!svga->chain4)
+ {
+ ht216->read_bank[0] >>= 2;
+ ht216->read_bank[1] >>= 2;
+ ht216->write_bank[0] >>= 2;
+ ht216->write_bank[1] >>= 2;
+ }
+ }
+// pclog("Remap - chain4=%i [e0]=%02x [e8]=%02x [e9]=%02x [f6]=%02x [fc]=%02x [f9]=%02x misc=%02x gdc[6]=%02x read[0]=%05X write[0]=%05X read[1]=%05X write[1]=%05X\n", svga->chain4, ht216->ht_regs[0xe0], ht216->ht_regs[0xe8], ht216->ht_regs[0xe9], ht216->ht_regs[0xf6], ht216->ht_regs[0xfc], ht216->ht_regs[0xf9], ht216->misc, svga->gdcreg[6], ht216->read_bank[0], ht216->write_bank[0], ht216->read_bank[1], ht216->write_bank[1]);
+}
+
+void ht216_recalctimings(svga_t *svga)
+{
+ ht216_t *ht216 = (ht216_t *)svga->p;
+
+// pclog("clk_sel = %i\n", ht216->clk_sel);
+ switch (ht216->clk_sel)
+ {
+ case 5: svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; break;
+ case 6: svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; break;
+ case 10: svga->clock = (cpuclock * (double)(1ull << 32)) / 80000000.0; break;
+ }
+ svga->lowres = !(ht216->ht_regs[0xc8] & HT_REG_C8_E256);
+ svga->ma_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 12);
+ svga->interlace = ht216->ht_regs[0xe0] & 1;
+
+ if (svga->bpp == 8 && !svga->lowres)
+ svga->render = svga_render_8bpp_highres;
+}
+
+static void ht216_hwcursor_draw(svga_t *svga, int displine)
+{
+// ht216_t *ht216 = (ht216_t *)svga->p;
+ int x;
+ uint32_t dat[2];
+ int offset = svga->hwcursor_latch.x + 32;
+
+ if (svga->interlace && svga->hwcursor_oddeven)
+ svga->hwcursor_latch.addr += 4;
+
+ 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+128] << 24) |
+ (svga->vram[svga->hwcursor_latch.addr+128+1] << 16) |
+ (svga->vram[svga->hwcursor_latch.addr+128+2] << 8) |
+ svga->vram[svga->hwcursor_latch.addr+128+3];
+
+ for (x = 0; x < 32; x++)
+ {
+ if (!(dat[0] & 0x80000000))
+ ((uint32_t *)buffer32->line[displine])[offset + x] = 0;
+ if (dat[1] & 0x80000000)
+ ((uint32_t *)buffer32->line[displine])[offset + x] ^= 0xffffff;
+
+ dat[0] <<= 1;
+ dat[1] <<= 1;
+ }
+
+ svga->hwcursor_latch.addr += 4;
+ if (svga->interlace && !svga->hwcursor_oddeven)
+ svga->hwcursor_latch.addr += 4;
+}
+
+static inline uint8_t extalu(int op, uint8_t input_a, uint8_t input_b)
+{
+ uint8_t val;
+
+ switch (op)
+ {
+ case 0x0: val = 0; break;
+ case 0x1: val = ~(input_a | input_b); break;
+ case 0x2: val = input_a & ~input_b; break;
+ case 0x3: val = ~input_b; break;
+ case 0x4: val = ~input_a & input_b; break;
+ case 0x5: val = ~input_a; break;
+ case 0x6: val = input_a ^ input_b; break;
+ case 0x7: val = ~(input_a & input_b); break;
+ case 0x8: val = input_a & input_b; break;
+ case 0x9: val = ~(input_a ^ input_b); break;
+ case 0xa: val = input_a; break;
+ case 0xb: val = input_a | ~input_b; break;
+ case 0xc: val = input_b; break;
+ case 0xd: val = ~input_a | input_b; break;
+ case 0xe: val = input_a | input_b; break;
+ case 0xf: default: val = 0xff; break;
+ }
+
+ return val;
+}
+
+/*Remap address for chain-4/doubleword style layout*/
+static inline uint32_t dword_remap(svga_t *svga, uint32_t in_addr)
+{
+ if (svga->packed_chain4)
+ return in_addr;
+ return ((in_addr & 0xfffc) << 2) | ((in_addr & 0x30000) >> 14) | (in_addr & ~0x3ffff);
+}
+
+static void ht216_dm_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t cpu_dat_unexpanded)
+{
+ svga_t *svga = &ht216->svga;
+ uint8_t vala, valb, valc, vald, wm = svga->writemask;
+ int writemask2 = svga->writemask;
+ uint8_t fg_data[4] = {0,0,0,0};
+
+ if (!(svga->gdcreg[6] & 1))
+ svga->fullchange = 2;
+ if (svga->chain4)
+ {
+ writemask2 = 1 << (addr & 3);
+ addr = dword_remap(svga, addr) & ~3;
+ }
+ else if (svga->chain2_write)
+ {
+ writemask2 &= ~0xa;
+ if (addr & 1)
+ writemask2 <<= 1;
+ addr &= ~1;
+ addr <<= 2;
+ }
+ else
+ {
+ addr<<=2;
+ }
+ if (addr >= svga->vram_max)
+ return;
+
+ svga->changedvram[addr >> 12]=changeframecount;
+
+ switch (ht216->ht_regs[0xfe] & HT_REG_FE_FBMC)
+ {
+ case 0x00:
+ fg_data[0] = fg_data[1] = fg_data[2] = fg_data[3] = cpu_dat;
+ break;
+ case 0x04:
+ if (ht216->ht_regs[0xfe] & HT_REG_FE_FBRC)
+ {
+ if (addr & 4)
+ {
+ fg_data[0] = (cpu_dat_unexpanded & (1 << (((addr + 4) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ fg_data[1] = (cpu_dat_unexpanded & (1 << (((addr + 5) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ fg_data[2] = (cpu_dat_unexpanded & (1 << (((addr + 6) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ fg_data[3] = (cpu_dat_unexpanded & (1 << (((addr + 7) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ }
+ else
+ {
+ fg_data[0] = (cpu_dat_unexpanded & (1 << (((addr + 0) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ fg_data[1] = (cpu_dat_unexpanded & (1 << (((addr + 1) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ fg_data[2] = (cpu_dat_unexpanded & (1 << (((addr + 2) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ fg_data[3] = (cpu_dat_unexpanded & (1 << (((addr + 3) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ }
+ }
+ else
+ {
+ if (addr & 4)
+ {
+ fg_data[0] = (ht216->ht_regs[0xf5] & (1 << (((addr + 4) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ fg_data[1] = (ht216->ht_regs[0xf5] & (1 << (((addr + 5) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ fg_data[2] = (ht216->ht_regs[0xf5] & (1 << (((addr + 6) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ fg_data[3] = (ht216->ht_regs[0xf5] & (1 << (((addr + 7) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ }
+ else
+ {
+ fg_data[0] = (ht216->ht_regs[0xf5] & (1 << (((addr + 0) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ fg_data[1] = (ht216->ht_regs[0xf5] & (1 << (((addr + 1) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ fg_data[2] = (ht216->ht_regs[0xf5] & (1 << (((addr + 2) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ fg_data[3] = (ht216->ht_regs[0xf5] & (1 << (((addr + 3) & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ }
+ }
+ break;
+ case 0x08:
+ fg_data[0] = ht216->ht_regs[0xec];
+ fg_data[1] = ht216->ht_regs[0xed];
+ fg_data[2] = ht216->ht_regs[0xee];
+ fg_data[3] = ht216->ht_regs[0xef];
+ break;
+ case 0x0c:
+ fg_data[0] = ht216->ht_regs[0xec];
+ fg_data[1] = ht216->ht_regs[0xed];
+ fg_data[2] = ht216->ht_regs[0xee];
+ fg_data[3] = ht216->ht_regs[0xef];
+ break;
+ }
+
+
+ switch (svga->writemode)
+ {
+ case 1:
+ if (writemask2 & 1) svga->vram[addr] = svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld;
+ break;
+ case 0:
+ if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled))
+ {
+ if (writemask2 & 1) svga->vram[addr] = fg_data[0];
+ if (writemask2 & 2) svga->vram[addr | 0x1] = fg_data[1];
+ if (writemask2 & 4) svga->vram[addr | 0x2] = fg_data[2];
+ if (writemask2 & 8) svga->vram[addr | 0x3] = fg_data[3];
+ }
+ else
+ {
+ if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
+ else vala = fg_data[0];
+ if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
+ else valb = fg_data[1];
+ if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
+ else valc = fg_data[2];
+ if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
+ else vald = fg_data[3];
+
+ switch (svga->gdcreg[3] & 0x18)
+ {
+ case 0: /*Set*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ break;
+ case 8: /*AND*/
+ if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
+ break;
+ case 0x10: /*OR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
+ break;
+ case 0x18: /*XOR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
+ break;
+ }
+// pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
+ }
+ break;
+ case 2:
+ if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled))
+ {
+ if (writemask2 & 1) svga->vram[addr] = (((cpu_dat & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (((cpu_dat & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (((cpu_dat & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (((cpu_dat & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ }
+ else
+ {
+ vala = ((cpu_dat & 1) ? 0xff : 0);
+ valb = ((cpu_dat & 2) ? 0xff : 0);
+ valc = ((cpu_dat & 4) ? 0xff : 0);
+ vald = ((cpu_dat & 8) ? 0xff : 0);
+ switch (svga->gdcreg[3] & 0x18)
+ {
+ case 0: /*Set*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ break;
+ case 8: /*AND*/
+ if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
+ break;
+ case 0x10: /*OR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
+ break;
+ case 0x18: /*XOR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
+ break;
+ }
+ }
+ break;
+ case 3:
+ wm = svga->gdcreg[8];
+ svga->gdcreg[8] &= cpu_dat;
+
+ vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
+ valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
+ valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
+ vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
+ switch (svga->gdcreg[3] & 0x18)
+ {
+ case 0: /*Set*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ break;
+ case 8: /*AND*/
+ if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
+ break;
+ case 0x10: /*OR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
+ break;
+ case 0x18: /*XOR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
+ break;
+ }
+ svga->gdcreg[8] = wm;
+ break;
+ }
+}
+
+static void ht216_dm_extalu_write(ht216_t *ht216, uint32_t addr, uint8_t cpu_dat, uint8_t bit_mask, uint8_t cpu_dat_unexpanded, uint8_t rop_select)
+{
+ /*Input B = CD.5
+ Input A = FE[3:2]
+ 00 = Set/Reset output mode
+ output = CPU-side ALU input
+ 01 = Solid fg/bg mode (3C4:FA/FB)
+ Bit mask = 3CF.F5 or CPU byte
+ 10 = Dithered fg (3CF:EC-EF)
+ 11 = RMW (dest data) (set if CD.5 = 1)
+ F/B ROP select = FE[5:4]
+ 00 = CPU byte
+ 01 = Bit mask (3CF:8)
+ 1x = (3C4:F5)*/
+ svga_t *svga = &ht216->svga;
+ uint8_t input_a = 0, input_b = 0;
+ uint8_t fg, bg;
+ uint8_t output;
+ uint32_t remapped_addr = dword_remap(svga, addr);
+
+ if (ht216->ht_regs[0xcd] & HT_REG_CD_RMWMDE) /*RMW*/
+ input_b = svga->vram[remapped_addr];
+ else
+ input_b = ht216->bg_latch[addr & 7];
+
+ switch (ht216->ht_regs[0xfe] & HT_REG_FE_FBMC)
+ {
+ case 0x00:
+ input_a = cpu_dat;
+ break;
+ case 0x04:
+ if (ht216->ht_regs[0xfe] & HT_REG_FE_FBRC)
+ input_a = (cpu_dat_unexpanded & (1 << ((addr & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ else
+ input_a = (ht216->ht_regs[0xf5] & (1 << ((addr & 7) ^ 7))) ? ht216->ht_regs[0xfa] : ht216->ht_regs[0xfb];
+ break;
+ case 0x08:
+ input_a = ht216->ht_regs[0xec + (addr & 3)];
+ break;
+ case 0x0c:
+ input_a = ht216->bg_latch[addr & 7];
+ break;
+ }
+
+ fg = extalu(ht216->ht_regs[0xce] >> 4, input_a, input_b);
+ bg = extalu(ht216->ht_regs[0xce] & 0xf, input_a, input_b);
+// svga->vram[addr]
+ output = (fg & rop_select) | (bg & ~rop_select);
+ svga->vram[addr] = (svga->vram[remapped_addr] & ~bit_mask) | (output & bit_mask);
+// pclog(" A=%02x B=%02x R=%02x FG=%02x BG=%02x ops=%02x val=%02x addr=%05x\n", input_a, input_b, rop_select, fg, bg, ht216->ht_regs[0xce], svga->vram[addr], addr);
+ svga->changedvram[remapped_addr >> 12] = changeframecount;
+}
+
+static void ht216_write_common(ht216_t *ht216, uint32_t addr, uint8_t val)
+{
+ /*Input B = CD.5
+ Input A = FE[3:2]
+ 00 = Set/Reset output mode
+ output = CPU-side ALU input
+ 01 = Solid fg/bg mode (3C4:FA/FB)
+ Bit mask = 3CF.F5 or CPU byte
+ 10 = Dithered fg (3CF:EC-EF)
+ 11 = RMW (dest data) (set if CD.5 = 1)
+ F/B ROP select = FE[5:4]
+ 00 = CPU byte
+ 01 = Bit mask (3CF:8)
+ 1x = (3C4:F5)
+ */
+ svga_t *svga = &ht216->svga;
+
+ cycles -= video_timing_write_b;
+ cycles_lost += video_timing_write_b;
+
+ egawrites++;
+
+ addr &= 0xfffff;
+
+// pclog("%08X %02x %08x\n", addr, svga->gdcreg[6], svga->banked_mask);
+
+ val = svga_rotate[svga->gdcreg[3] & 7][val];
+
+ if (ht216->ht_regs[0xcd] & HT_REG_CD_EXALU) /*Extended ALU*/
+ {
+ uint8_t bit_mask = 0, rop_select = 0;
+
+ switch (ht216->ht_regs[0xfe] & HT_REG_FE_FBRSL)
+ {
+ case 0x00:
+ rop_select = val;
+ break;
+ case 0x10:
+ rop_select = svga->gdcreg[8];
+ break;
+ case 0x20: case 0x30:
+ rop_select = ht216->ht_regs[0xf5];
+ break;
+ }
+
+ switch (ht216->ht_regs[0xcd] & HT_REG_CD_BMSKSL)
+ {
+ case 0x00:
+ bit_mask = svga->gdcreg[8];
+ break;
+ case 0x04:
+ bit_mask = val;
+ break;
+ case 0x08: case 0x0c:
+ bit_mask = ht216->ht_regs[0xf5];
+ break;
+ }
+
+ if (ht216->ht_regs[0xcd] & HT_REG_CD_FP8PCEXP) /*1->8 bit expansion*/
+ {
+ addr = (addr << 3) & 0xfffff;
+ ht216_dm_extalu_write(ht216, addr, (val & 0x80) ? 0xff : 0, (bit_mask & 0x80) ? 0xff : 0, val, (rop_select & 0x80) ? 0xff : 0);
+ ht216_dm_extalu_write(ht216, addr + 1, (val & 0x40) ? 0xff : 0, (bit_mask & 0x40) ? 0xff : 0, val, (rop_select & 0x40) ? 0xff : 0);
+ ht216_dm_extalu_write(ht216, addr + 2, (val & 0x20) ? 0xff : 0, (bit_mask & 0x20) ? 0xff : 0, val, (rop_select & 0x20) ? 0xff : 0);
+ ht216_dm_extalu_write(ht216, addr + 3, (val & 0x10) ? 0xff : 0, (bit_mask & 0x10) ? 0xff : 0, val, (rop_select & 0x10) ? 0xff : 0);
+ ht216_dm_extalu_write(ht216, addr + 4, (val & 0x08) ? 0xff : 0, (bit_mask & 0x08) ? 0xff : 0, val, (rop_select & 0x08) ? 0xff : 0);
+ ht216_dm_extalu_write(ht216, addr + 5, (val & 0x04) ? 0xff : 0, (bit_mask & 0x04) ? 0xff : 0, val, (rop_select & 0x04) ? 0xff : 0);
+ ht216_dm_extalu_write(ht216, addr + 6, (val & 0x02) ? 0xff : 0, (bit_mask & 0x02) ? 0xff : 0, val, (rop_select & 0x02) ? 0xff : 0);
+ ht216_dm_extalu_write(ht216, addr + 7, (val & 0x01) ? 0xff : 0, (bit_mask & 0x01) ? 0xff : 0, val, (rop_select & 0x01) ? 0xff : 0);
+ }
+ else
+ ht216_dm_extalu_write(ht216, addr, val, bit_mask, val, rop_select);
+ }
+ else
+ {
+ if (ht216->ht_regs[0xcd] & HT_REG_CD_FP8PCEXP) /*1->8 bit expansion*/
+ {
+ addr = (addr << 3) & 0xfffff;
+ ht216_dm_write(ht216, addr, (val & 0x80) ? 0xff : 0, val);
+ ht216_dm_write(ht216, addr + 1, (val & 0x40) ? 0xff : 0, val);
+ ht216_dm_write(ht216, addr + 2, (val & 0x20) ? 0xff : 0, val);
+ ht216_dm_write(ht216, addr + 3, (val & 0x10) ? 0xff : 0, val);
+ ht216_dm_write(ht216, addr + 4, (val & 0x08) ? 0xff : 0, val);
+ ht216_dm_write(ht216, addr + 5, (val & 0x04) ? 0xff : 0, val);
+ ht216_dm_write(ht216, addr + 6, (val & 0x02) ? 0xff : 0, val);
+ ht216_dm_write(ht216, addr + 7, (val & 0x01) ? 0xff : 0, val);
+ }
+ else
+ ht216_dm_write(ht216, addr, val, val);
+ }
+}
+
+static void ht216_write(uint32_t addr, uint8_t val, void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+ svga_t *svga = &ht216->svga;
+
+/* if (ht216->ht_regs[0xcd])
+ pclog("ht216_write: [CD]=%02x [FE]=%02x %08x %02x ", ht216->ht_regs[0xcd], ht216->ht_regs[0xfe], addr, val);
+ pclog("ht216_write : %05X %02X ", addr, val);*/
+ addr &= svga->banked_mask;
+ addr = (addr & 0x7fff) + ht216->write_bank[(addr >> 15) & 1];
+// pclog("phys_addr=%05x\n", addr);
+ if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe])
+ svga_write_linear(addr, val, &ht216->svga);
+ else
+ {
+ ht216_write_common(ht216, addr, val);
+ }
+}
+static void ht216_writew(uint32_t addr, uint16_t val, void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+ svga_t *svga = &ht216->svga;
+
+ addr &= svga->banked_mask;
+ addr = (addr & 0x7fff) + ht216->write_bank[(addr >> 15) & 1];
+ if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe])
+ svga_writew_linear(addr, val, &ht216->svga);
+ else
+ {
+ ht216_write_common(ht216, addr, val);
+ ht216_write_common(ht216, addr+1, val >> 8);
+ }
+}
+static void ht216_writel(uint32_t addr, uint32_t val, void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+ svga_t *svga = &ht216->svga;
+
+ addr &= svga->banked_mask;
+ addr = (addr & 0x7fff) + ht216->write_bank[(addr >> 15) & 1];
+ if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe])
+ svga_writel_linear(addr, val, &ht216->svga);
+ else
+ {
+ ht216_write_common(ht216, addr, val);
+ ht216_write_common(ht216, addr+1, val >> 8);
+ ht216_write_common(ht216, addr+2, val >> 16);
+ ht216_write_common(ht216, addr+3, val >> 24);
+ }
+}
+
+static void ht216_write_linear(uint32_t addr, uint8_t val, void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+ svga_t *svga = &ht216->svga;
+
+ if (!svga->chain4) /*Bits 16 and 17 of linear address seem to be unused in planar modes*/
+ addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2);
+
+ if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe])
+ svga_write_linear(addr, val, &ht216->svga);
+ else
+ ht216_write_common(ht216, addr, val);
+}
+static void ht216_writew_linear(uint32_t addr, uint16_t val, void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+ svga_t *svga = &ht216->svga;
+
+ if (!svga->chain4)
+ addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2);
+
+ if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe])
+ svga_writew_linear(addr, val, &ht216->svga);
+ else
+ {
+ ht216_write_common(ht216, addr, val);
+ ht216_write_common(ht216, addr+1, val >> 8);
+ }
+}
+static void ht216_writel_linear(uint32_t addr, uint32_t val, void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+ svga_t *svga = &ht216->svga;
+
+ if (!svga->chain4)
+ addr = (addr & 0xffff) | ((addr & 0xc0000) >> 2);
+
+ if (!ht216->ht_regs[0xcd] && !ht216->ht_regs[0xfe])
+ svga_writel_linear(addr, val, &ht216->svga);
+ else
+ {
+ ht216_write_common(ht216, addr, val);
+ ht216_write_common(ht216, addr+1, val >> 8);
+ ht216_write_common(ht216, addr+2, val >> 16);
+ ht216_write_common(ht216, addr+3, val >> 24);
+ }
+}
+
+static uint8_t ht216_read_common(ht216_t *ht216, uint32_t addr)
+{
+ svga_t *svga = &ht216->svga;
+ uint8_t temp, temp2, temp3, temp4;
+ int readplane = svga->readplane;
+ uint32_t latch_addr;
+
+ if (ht216->ht_regs[0xc8] & HT_REG_C8_MOVSB)
+ addr <<= 3;
+// pclog("%08X\n", addr);
+
+ addr &= 0xfffff;
+
+ cycles -= video_timing_read_b;
+ cycles_lost += video_timing_read_b;
+
+ egareads++;
+
+ if (svga->chain4)
+ {
+// if (ht216->ht_regs[0xcd])
+// pclog(" addr=%08x decode_mask=%08x vram_max=%08x\n", addr, svga->decode_mask, svga->vram_max);
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return 0xff;
+
+ latch_addr = (addr & svga->vram_mask) & ~7;
+ if (ht216->ht_regs[0xcd] & HT_REG_CD_ASTODE)
+ latch_addr += (svga->gdcreg[3] & 7);
+ ht216->bg_latch[0] = svga->vram[dword_remap(svga, latch_addr)];
+ ht216->bg_latch[1] = svga->vram[dword_remap(svga, latch_addr + 1)];
+ ht216->bg_latch[2] = svga->vram[dword_remap(svga, latch_addr + 2)];
+ ht216->bg_latch[3] = svga->vram[dword_remap(svga, latch_addr + 3)];
+ ht216->bg_latch[4] = svga->vram[dword_remap(svga, latch_addr + 4)];
+ ht216->bg_latch[5] = svga->vram[dword_remap(svga, latch_addr + 5)];
+ ht216->bg_latch[6] = svga->vram[dword_remap(svga, latch_addr + 6)];
+ ht216->bg_latch[7] = svga->vram[dword_remap(svga, latch_addr + 7)];
+
+/*pclog(" Read %08x %02x %02x %02x %02x %02x %02x %02x %02x\n", addr,
+ ht216->bg_latch[0],ht216->bg_latch[1],ht216->bg_latch[2],ht216->bg_latch[3],
+ ht216->bg_latch[4],ht216->bg_latch[5],ht216->bg_latch[6],ht216->bg_latch[7]);*/
+
+ return svga->vram[dword_remap(svga, addr) & svga->vram_mask];
+ }
+ else if (svga->chain2_read)
+ {
+ readplane = (readplane & 2) | (addr & 1);
+ addr &= ~1;
+ addr <<= 2;
+ }
+ else
+ addr<<=2;
+
+ addr &= svga->decode_mask;
+
+ if (addr >= svga->vram_max)
+ return 0xff;
+
+ addr &= svga->vram_mask;
+
+ latch_addr = addr & ~7;
+ if (ht216->ht_regs[0xcd] & HT_REG_CD_ASTODE)
+ {
+ int offset = addr & 7;
+
+ ht216->bg_latch[0] = svga->vram[latch_addr | offset];
+ ht216->bg_latch[1] = svga->vram[latch_addr | ((offset + 1) & 7)];
+ ht216->bg_latch[2] = svga->vram[latch_addr | ((offset + 2) & 7)];
+ ht216->bg_latch[3] = svga->vram[latch_addr | ((offset + 3) & 7)];
+ ht216->bg_latch[4] = svga->vram[latch_addr | ((offset + 4) & 7)];
+ ht216->bg_latch[5] = svga->vram[latch_addr | ((offset + 5) & 7)];
+ ht216->bg_latch[6] = svga->vram[latch_addr | ((offset + 6) & 7)];
+ ht216->bg_latch[7] = svga->vram[latch_addr | ((offset + 7) & 7)];
+ }
+ else
+ {
+ ht216->bg_latch[0] = svga->vram[latch_addr];
+ ht216->bg_latch[1] = svga->vram[latch_addr | 1];
+ ht216->bg_latch[2] = svga->vram[latch_addr | 2];
+ ht216->bg_latch[3] = svga->vram[latch_addr | 3];
+ ht216->bg_latch[4] = svga->vram[latch_addr | 4];
+ ht216->bg_latch[5] = svga->vram[latch_addr | 5];
+ ht216->bg_latch[6] = svga->vram[latch_addr | 6];
+ ht216->bg_latch[7] = svga->vram[latch_addr | 7];
+ }
+/*pclog(" Read %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ ht216->bg_latch[0],ht216->bg_latch[1],ht216->bg_latch[2],ht216->bg_latch[3],
+ ht216->bg_latch[4],ht216->bg_latch[5],ht216->bg_latch[6],ht216->bg_latch[7]);*/
+ if (addr & 4)
+ {
+ svga->la = ht216->bg_latch[4];
+ svga->lb = ht216->bg_latch[5];
+ svga->lc = ht216->bg_latch[6];
+ svga->ld = ht216->bg_latch[7];
+ }
+ else
+ {
+ svga->la = ht216->bg_latch[0];
+ svga->lb = ht216->bg_latch[1];
+ svga->lc = ht216->bg_latch[2];
+ svga->ld = ht216->bg_latch[3];
+ }
+ if (svga->readmode)
+ {
+ temp = svga->la;
+ temp ^= (svga->colourcompare & 1) ? 0xff : 0;
+ temp &= (svga->colournocare & 1) ? 0xff : 0;
+ temp2 = svga->lb;
+ temp2 ^= (svga->colourcompare & 2) ? 0xff : 0;
+ temp2 &= (svga->colournocare & 2) ? 0xff : 0;
+ temp3 = svga->lc;
+ temp3 ^= (svga->colourcompare & 4) ? 0xff : 0;
+ temp3 &= (svga->colournocare & 4) ? 0xff : 0;
+ temp4 = svga->ld;
+ temp4 ^= (svga->colourcompare & 8) ? 0xff : 0;
+ temp4 &= (svga->colournocare & 8) ? 0xff : 0;
+ return ~(temp | temp2 | temp3 | temp4);
+ }
+//printf("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane);
+ return svga->vram[addr | readplane];
+
+// return svga_read_linear(addr, &ht216->svga);
+}
+static uint8_t ht216_read(uint32_t addr, void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+ svga_t *svga = &ht216->svga;
+
+// if (ht216->ht_regs[0xcd])
+// pclog("ht216_read: [CD]=%02x [FC]=%02x %08x\n", ht216->ht_regs[0xcd], ht216->ht_regs[0xfc], addr);
+// pclog("ht216_read : %05X ", addr);
+ addr &= svga->banked_mask;
+ addr = (addr & 0x7fff) + ht216->read_bank[(addr >> 15) & 1];
+
+ return ht216_read_common(ht216, addr);
+}
+
+/*static uint16_t ht216_readw(uint32_t addr, void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+ svga_t *svga = &ht216->svga;
+
+ addr &= svga->banked_mask;
+ addr = (addr & 0x7fff) + ht216->write_bank[(addr >> 15) & 1];
+ return svga_readw_linear(addr, &ht216->svga);
+}*/
+
+static uint8_t ht216_read_linear(uint32_t addr, void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+ svga_t *svga = &ht216->svga;
+
+ if (svga->chain4)
+ return ht216_read_common(ht216, addr);
+ else
+ return ht216_read_common(ht216, (addr & 0xffff) | ((addr & 0xc0000) >> 2));
+}
+
+void *ht216_init()
+{
+ ht216_t *ht216 = malloc(sizeof(ht216_t));
+ svga_t *svga = &ht216->svga;
+ memset(ht216, 0, sizeof(ht216_t));
+
+ io_sethandler(0x03c0, 0x0020, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216);
+ io_sethandler(0x46e8, 0x0001, ht216_in, NULL, NULL, ht216_out, NULL, NULL, ht216);
+
+ svga_init(&ht216->svga, ht216, 1 << 20, /*1MB*/
+ ht216_recalctimings,
+ ht216_in, ht216_out,
+ ht216_hwcursor_draw,
+ NULL);
+ svga->hwcursor.ysize = 32;
+ ht216->vram_mask = 0xfffff;
+ svga->decode_mask = 0xfffff;
+
+ mem_mapping_set_handler(&ht216->svga.mapping, ht216_read, NULL/*ht216_readw*/, NULL, ht216_write, ht216_writew, ht216_writel);
+ mem_mapping_set_p(&ht216->svga.mapping, ht216);
+ mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, ht216_writel_linear, NULL, 0, &ht216->svga);
+
+ svga->bpp = 8;
+ svga->miscout = 1;
+
+ ht216->ht_regs[0xb4] = 0x08; /*32-bit DRAM bus*/
+
+ return ht216;
+}
+
+static void *ht216_pb410a_init()
+{
+ ht216_t *ht216 = ht216_init();
+
+ return ht216;
+}
+
+void ht216_close(void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+
+ svga_close(&ht216->svga);
+
+ free(ht216);
+}
+
+void ht216_speed_changed(void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+
+ svga_recalctimings(&ht216->svga);
+}
+
+void ht216_force_redraw(void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+
+ ht216->svga.fullchange = changeframecount;
+}
+
+void ht216_add_status_info(char *s, int max_len, void *p)
+{
+ ht216_t *ht216 = (ht216_t *)p;
+
+ svga_add_status_info(s, max_len, &ht216->svga);
+}
+
+device_t ht216_32_pb410a_device =
+{
+ "Headland HT216-32 (Packard Bell PB410A)",
+ 0,
+ ht216_pb410a_init,
+ ht216_close,
+ NULL,
+ ht216_speed_changed,
+ ht216_force_redraw,
+ ht216_add_status_info
+};
diff --git a/src/vid_ht216.h b/src/vid_ht216.h
new file mode 100644
index 0000000..c5e7b3a
--- /dev/null
+++ b/src/vid_ht216.h
@@ -0,0 +1 @@
+extern device_t ht216_32_pb410a_device;
diff --git a/src/vid_im1024.c b/src/vid_im1024.c
new file mode 100644
index 0000000..386059a
--- /dev/null
+++ b/src/vid_im1024.c
@@ -0,0 +1,906 @@
+#include
+#include
+#include
+#include "ibm.h"
+#include "device.h"
+#include "io.h"
+#include "mem.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_pgc.h"
+#include "vid_im1024.h"
+
+/* This implements just enough of the Vermont Microsystems IM-1024 to
+ * support the Windows 1.03 driver. Functions are partially implemented
+ * or hardwired to the behaviour expected by the Windows driver.
+ *
+ * One major difference seems to be that in hex mode, coordinates are
+ * passed as 2-byte integer words rather than 4-byte fixed-point fractions.
+ * I don't know what triggers this, so for now it's always on.
+ */
+
+extern uint8_t fontdat12x18[256][36];
+
+typedef struct im1024_t
+{
+ pgc_core_t pgc;
+ unsigned char fontx[256];
+ unsigned char fonty[256];
+ unsigned char font[256][128];
+
+ unsigned char *fifo;
+ unsigned fifo_len, fifo_wrptr, fifo_rdptr;
+} im1024_t;
+
+/* As well as the usual PGC ring buffer at 0xC6000, the IM1024 appears to
+ * have an alternate method of passing commands. This is enabled by setting
+ * 0xC6330 to 1, and then:
+ *
+ * CX = count to write
+ * SI -> bytes to write
+ *
+ * Set pending bytes to 0
+ * Read [C6331]. This gives number of bytes that can be written:
+ * 0xFF => 0, 0xFE => 1, 0xFD => 2 etc.
+ * Write that number of bytes to C6000.
+ * If there are more to come, go back to reading [C6331].
+ * As far as I can see, at least one byte is always written; there's no
+ * provision to pause if the queue is full.
+ *
+ * I am implementing this by holding a FIFO of unlimited depth in the
+ * IM1024 to receive the data.
+ *
+ */
+
+static void fifo_write(im1024_t *im1024, unsigned char val)
+{
+/* PGCLOG(("fifo_write: %02x [rd=%04x wr=%04x]\n", val,
+ im1024->fifo_rdptr, im1024->fifo_wrptr)); */
+ if (((im1024->fifo_wrptr + 1) % im1024->fifo_len) == im1024->fifo_rdptr)
+ {
+/* FIFO is full. Double its size. */
+ unsigned char *buf;
+
+ PGCLOG(("fifo_resize: %d to %d\n",
+ im1024->fifo_len, 2 * im1024->fifo_len));
+
+ buf = realloc(im1024->fifo, 2 * im1024->fifo_len);
+ if (!buf) return;
+/* Move the [0..wrptr] range to the newly-allocated area [len..len+wrptr] */
+ memmove(buf + im1024->fifo_len, buf, im1024->fifo_wrptr);
+ im1024->fifo = buf;
+ im1024->fifo_wrptr += im1024->fifo_len;
+ im1024->fifo_len *= 2;
+ }
+/* Append to the queue */
+ im1024->fifo[im1024->fifo_wrptr] = val;
+ ++im1024->fifo_wrptr;
+
+/* Wrap if end of buffer reached */
+ if (im1024->fifo_wrptr >= im1024->fifo_len)
+ {
+ im1024->fifo_wrptr = 0;
+ }
+}
+
+
+static int fifo_read(im1024_t *im1024)
+{
+ uint8_t result;
+
+ if (im1024->fifo_wrptr == im1024->fifo_rdptr)
+ {
+ return -1; /* FIFO empty */
+ }
+ result = im1024->fifo[im1024->fifo_rdptr];
+ ++im1024->fifo_rdptr;
+ if (im1024->fifo_rdptr >= im1024->fifo_len)
+ {
+ im1024->fifo_rdptr = 0;
+ }
+/*
+ PGCLOG(("fifo_read: %02x\n", result));
+*/
+ return result;
+
+}
+
+/* Where a normal PGC would just read from the ring buffer at 0xC6300, the
+ * IM-1024 can read either from this or from its internal FIFO. The internal
+ * FIFO has priority. */
+int im1024_input_byte(pgc_core_t *pgc, uint8_t *result)
+{
+ im1024_t *im1024 = (im1024_t *)pgc;
+
+ /* If input buffer empty, wait for it to fill */
+ while ((im1024->fifo_wrptr == im1024->fifo_rdptr) &&
+ (pgc->mapram[0x300] == pgc->mapram[0x301]))
+ {
+ pgc->waiting_input_fifo = 1;
+ pgc_sleep(pgc);
+ }
+ if (pgc->mapram[0x3FF]) /* Reset triggered */
+ {
+ pgc_reset(pgc);
+ return 0;
+ }
+ if (im1024->fifo_wrptr == im1024->fifo_rdptr)
+ {
+ *result = pgc->mapram[pgc->mapram[0x301]];
+ ++pgc->mapram[0x301];
+ }
+ else
+ {
+ *result = fifo_read(im1024);
+ }
+ return 1;
+}
+
+/* Macros to disable clipping and save clip state */
+#define PUSHCLIP { \
+ uint16_t vp_x1, vp_x2, vp_y1, vp_y2; \
+ vp_x1 = pgc->vp_x1; \
+ vp_y1 = pgc->vp_y1; \
+ vp_x2 = pgc->vp_x2; \
+ vp_y2 = pgc->vp_y2; \
+ pgc->vp_x1 = 0; \
+ pgc->vp_y1 = 0; \
+ pgc->vp_x2 = pgc->maxw - 1; \
+ pgc->vp_y2 = pgc->maxh - 1; \
+
+/* And to restore clip state */
+#define POPCLIP \
+ pgc->vp_x1 = vp_x1; \
+ pgc->vp_y1 = vp_y1; \
+ pgc->vp_x2 = vp_x2; \
+ pgc->vp_y2 = vp_y2; \
+ }
+
+
+/* Override memory read to return FIFO space */
+uint8_t im1024_read(uint32_t addr, void *p)
+{
+ im1024_t *im1024 = (im1024_t *)p;
+
+ if (addr == 0xC6331 && im1024->pgc.mapram[0x330] == 1)
+ {
+ return 0x80; /* Hardcode that there are 128 bytes
+ * free */
+ }
+ return pgc_read(addr, &im1024->pgc);
+}
+
+/* Override memory write to handle writes to the FIFO */
+void im1024_write(uint32_t addr, uint8_t val, void *p)
+{
+ im1024_t *im1024 = (im1024_t *)p;
+
+ /* If we are in 'fast' input mode, send all writes to the internal
+ * FIFO */
+ if (addr >= 0xC6000 && addr < 0xC6100 && im1024->pgc.mapram[0x330] == 1)
+ {
+ fifo_write(im1024, val);
+/*
+ PGCLOG(("im1024_write(%02x)\n", val));
+*/
+ if (im1024->pgc.waiting_input_fifo)
+ {
+ im1024->pgc.waiting_input_fifo = 0;
+ pgc_wake(&im1024->pgc);
+ }
+ return;
+ }
+ pgc_write(addr, val, &im1024->pgc);
+}
+
+
+
+/* I don't know what the IMGSIZ command does, only that the Windows driver
+ * issues it. So just parse and ignore it */
+void hndl_imgsiz(pgc_core_t *pgc)
+{
+ int16_t w,h;
+ uint8_t a,b;
+// im1024_t *im1024 = (im1024_t *)pgc;
+
+ if (!pgc_param_word(pgc, &w)) return;
+ if (!pgc_param_word(pgc, &h)) return;
+ if (!pgc_param_byte(pgc, &a)) return;
+ if (!pgc_param_byte(pgc, &b)) return;
+
+ PGCLOG(("IMGSIZ %d,%d,%d,%d\n", w,h,a,b));
+}
+
+
+/* I don't know what the IPREC command does, only that the Windows driver
+ * issues it. So just parse and ignore it */
+void hndl_iprec(pgc_core_t *pgc)
+{
+ uint8_t param;
+// im1024_t *im1024 = (im1024_t *)pgc;
+
+ if (!pgc_param_byte(pgc, ¶m)) return;
+
+ PGCLOG(("IPREC %d\n", param));
+}
+
+/* I think PAN controls which part of the 1024x1024 framebuffer is displayed
+ * in the 1024x800 visible screen. */
+void hndl_pan(pgc_core_t *pgc)
+{
+ int16_t x,y;
+
+ if (!pgc_param_word(pgc, &x)) return;
+ if (!pgc_param_word(pgc, &y)) return;
+
+ PGCLOG(("PAN %d,%d\n", x, y));
+
+ pgc->pan_x = x;
+ pgc->pan_y = y;
+}
+
+/* PLINE draws a non-filled polyline at a fixed position */
+void hndl_pline(pgc_core_t *pgc)
+{
+ int16_t x[257];
+ int16_t y[257];
+ uint8_t count;
+ unsigned n;
+ uint16_t linemask = pgc->line_pattern;
+
+ if (!pgc_param_byte(pgc, &count)) return;
+
+ PGCLOG(("PLINE (%d) ", count));
+ for (n = 0; n < count; n++)
+ {
+ if (!pgc_param_word(pgc, &x[n])) return;
+ if (!pgc_param_word(pgc, &y[n])) return;
+ PGCLOG((" (%d,%d)\n", x[n], y[n]));
+ }
+ for (n = 1; n < count; n++)
+ {
+ linemask = pgc_draw_line(pgc, x[n - 1] << 16, y[n - 1] << 16,
+ x[n] << 16, y[n] << 16, linemask);
+ }
+}
+
+
+/* Blit a single row of pixels from one location to another. To avoid
+ * difficulties if the two overlap, read both rows into memory, process them
+ * there, and write the result back. */
+void blkmov_row(pgc_core_t *pgc, int16_t x0, int16_t x1, int16_t x2,
+ int16_t sy, int16_t ty)
+{
+ int16_t x;
+ uint8_t src[1024];
+ uint8_t dst[1024];
+
+ for (x = x0; x <= x1; x++)
+ {
+ src[x - x0] = pgc_read_pixel(pgc, x, sy);
+ dst[x - x0] = pgc_read_pixel(pgc, x - x0 + x2, ty);
+ }
+ for (x = x0; x <= x1; x++)
+ {
+ switch (pgc->draw_mode)
+ {
+ default:
+ case 0: pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0]); break;
+ case 1: pgc_write_pixel(pgc, (x - x0 + x2), ty, dst[x - x0] ^ 0xFF); break;
+ case 2: pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0] ^ dst[x - x0]); break;
+ case 3: pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0] & dst[x - x0]); break;
+ }
+ }
+
+}
+
+
+/* BLKMOV blits a rectangular area from one location to another, with no
+ * clipping. */
+void hndl_blkmov(pgc_core_t *pgc)
+{
+ int16_t x0,y0;
+ int16_t x1,y1;
+ int16_t x2,y2;
+ int16_t y;
+// im1024_t *im1024 = (im1024_t *)pgc;
+
+ if (!pgc_param_word(pgc, &x0)) return;
+ if (!pgc_param_word(pgc, &y0)) return;
+ if (!pgc_param_word(pgc, &x1)) return;
+ if (!pgc_param_word(pgc, &y1)) return;
+ if (!pgc_param_word(pgc, &x2)) return;
+ if (!pgc_param_word(pgc, &y2)) return;
+
+ PGCLOG(("BLKMOV %d,%d,%d,%d,%d,%d\n", x0,y0,x1,y1,x2,y2));
+
+ /* Disable clipping */
+ PUSHCLIP
+
+ /* Either go down from the top, or up from the bottom, depending
+ * whether areas might overlap */
+ if (y2 <= y0)
+ {
+ for (y = y0; y <= y1; y++)
+ {
+ blkmov_row(pgc, x0, x1, x2, y, y - y0 + y2);
+ }
+ }
+ else
+ {
+ for (y = y1; y >= y0; y--)
+ {
+ blkmov_row(pgc, x0, x1, x2, y, y - y0 + y2);
+ }
+ }
+ /* Restore clipping */
+ POPCLIP
+}
+
+
+/* This overrides the PGC ELIPSE command to parse its parameters as words
+ * rather than coordinates */
+static void hndl_ellipse(pgc_core_t *pgc)
+{
+ int16_t x, y;
+
+ if (!pgc_param_word(pgc, &x)) return;
+ if (!pgc_param_word(pgc, &y)) return;
+
+ PGCLOG(("ELLIPSE %d,%d @ %d,%d\n", x,y,
+ pgc->x >> 16, pgc->y >> 16));
+ pgc_draw_ellipse(pgc, x << 16, y << 16);
+}
+
+
+
+/* This overrides the PGC MOVE command to parse its parameters as words
+ * rather than coordinates */
+static void hndl_move(pgc_core_t *pgc)
+{
+ int16_t x, y;
+
+ if (!pgc_param_word(pgc, &x)) return;
+ if (!pgc_param_word(pgc, &y)) return;
+
+ pgc->x = x << 16;
+ pgc->y = y << 16;
+ PGCLOG(("MOVE %d,%d\n", x,y));
+}
+
+/* This overrides the PGC DRAW command to parse its parameters as words
+ * rather than coordinates */
+static void hndl_draw(pgc_core_t *pgc)
+{
+ int16_t x, y;
+
+ if (!pgc_param_word(pgc, &x)) return;
+ if (!pgc_param_word(pgc, &y)) return;
+
+ PGCLOG(("DRAW %d,%d to %d,%d\n",
+ pgc->x >> 16, pgc->y >> 16, x, y));
+ pgc_draw_line(pgc, pgc->x, pgc->y, x << 16, y << 16, pgc->line_pattern);
+ pgc->x = x << 16;
+ pgc->y = y << 16;
+}
+
+
+
+
+/* This overrides the PGC POLY command to parse its parameters as words
+ * rather than coordinates */
+static void hndl_poly(pgc_core_t *pgc)
+{
+ int32_t *x, *y;
+ int32_t n;
+ int16_t xw, yw, mask;
+ unsigned realcount = 0;
+ int parsing = 1;
+ int as = 256;
+
+ x = malloc(as * sizeof(int32_t));
+ y = malloc(as * sizeof(int32_t));
+
+ if (!x || !y)
+ {
+ PGCLOG(("hndl_poly: malloc failed\n"));
+ return;
+ }
+ while (parsing)
+ {
+ uint8_t count;
+ if (!pgc_param_byte(pgc, &count)) return;
+
+ if (count + realcount >= as)
+ {
+ int32_t *nx, *ny;
+
+ nx = realloc(x, 2 * as * sizeof(int32_t));
+ ny = realloc(y, 2 * as * sizeof(int32_t));
+ if (!x || !y)
+ {
+ PGCLOG(("hndl_poly: realloc failed\n"));
+ break;
+ }
+ x = nx;
+ y = ny;
+ as *= 2;
+ }
+
+ for (n = 0; n < count; n++)
+ {
+ if (!pgc_param_word(pgc, &xw)) return;
+ if (!pgc_param_word(pgc, &yw)) return;
+
+ /* Skip degenerate line segments */
+ if (realcount > 0 &&
+ (xw << 16) == x[realcount - 1] &&
+ (yw << 16) == y[realcount - 1])
+ {
+ continue;
+ }
+ x[realcount] = xw << 16;
+ y[realcount] = yw << 16;
+ ++realcount;
+ }
+/* If we're in a command list, peek ahead to see if the next command is
+ * also POLY. If so, that's a continuation of this polygon! */
+ parsing = 0;
+ if (pgc->clcur && (pgc->clcur->rdptr+1) < pgc->clcur->wrptr &&
+ pgc->clcur->list[pgc->clcur->rdptr] == 0x30)
+ {
+ PGCLOG(("hndl_poly: POLY continues!\n"));
+ parsing = 1;
+ /* Swallow the POLY */
+ ++pgc->clcur->rdptr;
+ }
+
+ }
+
+ PGCLOG(("POLY (%d) fill_mode=%d\n", realcount, pgc->fill_mode));
+ for (n = 0; n < realcount; n++)
+ {
+ PGCLOG((" (%d,%d)\n", x[n] >> 16, y[n] >> 16));
+ }
+ if (pgc->fill_mode)
+ {
+ pgc_fill_polygon(pgc, realcount, x, y);
+ }
+ /* Now draw borders */
+ mask = pgc->line_pattern;
+ for (n = 1; n < realcount; n++)
+ {
+ mask = pgc_draw_line(pgc, x[n - 1], y[n - 1], x[n], y[n], mask);
+ }
+ pgc_draw_line(pgc, x[realcount - 1], y[realcount - 1], x[0], y[0], mask);
+ free(y);
+ free(x);
+}
+
+
+static int parse_poly(pgc_core_t *pgc, pgc_commandlist_t *cl, int c)
+{
+ uint8_t count;
+
+ PGCLOG(("parse_poly\n"));
+ if (!pgc_param_byte(pgc, &count)) return 0;
+
+ PGCLOG(("parse_poly: count=%02x\n", count));
+ if (!pgc_commandlist_append(cl, count))
+ {
+ pgc_error(pgc, PGC_ERROR_OVERFLOW);
+ return 0;
+ }
+ PGCLOG(("parse_poly: parse %d words\n", 2 * count));
+ return pgc_parse_words(pgc, cl, count * 2);
+}
+
+
+
+/* This overrides the PGC RECT command to parse its parameters as words
+ * rather than coordinates */
+static void hndl_rect(pgc_core_t *pgc)
+{
+ int16_t x0, y0, x1, y1, p, q;
+
+ x0 = pgc->x >> 16;
+ y0 = pgc->y >> 16;
+
+ if (!pgc_param_word(pgc, &x1)) return;
+ if (!pgc_param_word(pgc, &y1)) return;
+
+ /* Convert to raster coords */
+ pgc_sto_raster(pgc, &x0, &y0);
+ pgc_sto_raster(pgc, &x1, &y1);
+
+ if (x0 > x1) { p = x0; x0 = x1; x1 = p; }
+ if (y0 > y1) { q = y0; y0 = y1; y1 = q; }
+
+ PGCLOG(("RECT (%d,%d) -> (%d,%d)\n", x0, y0, x1, y1));
+
+ if (pgc->fill_mode)
+ {
+ for (p = y0; p <= y1; p++)
+ {
+ pgc_fill_line_r(pgc, x0, x1, p);
+ }
+ }
+ else /* Outline: 4 lines */
+ {
+ p = pgc->line_pattern;
+ p = pgc_draw_line_r(pgc, x0, y0, x1, y0, p);
+ p = pgc_draw_line_r(pgc, x1, y0, x1, y1, p);
+ p = pgc_draw_line_r(pgc, x1, y1, x0, y1, p);
+ p = pgc_draw_line_r(pgc, x0, y1, x0, y0, p);
+ }
+}
+
+
+/* TODO: Text drawing should probably be implemented in vid_pgc.c rather
+ * than vid_im1024.c */
+static void hndl_tdefin(pgc_core_t *pgc)
+{
+ unsigned char ch, bt;
+ unsigned char rows, cols;
+ unsigned len, n;
+// unsigned x = 0;
+ im1024_t * im1024 = (im1024_t *)pgc;
+
+ if (!pgc_param_byte(pgc, &ch)) return;
+ if (!pgc_param_byte(pgc, &cols)) return;
+ if (!pgc_param_byte(pgc, &rows)) return;
+
+ PGCLOG(("TDEFIN (%d,%d,%d) 0x%02x 0x%02x\n", ch, rows, cols,
+ pgc->mapram[0x300], pgc->mapram[0x301]));
+
+ len = ((cols + 7) / 8) * rows;
+ for (n = 0; n < len; n++)
+ {
+// char buf[10];
+// unsigned char mask;
+
+ if (!pgc_param_byte(pgc, &bt)) return;
+
+// buf[0] = 0;
+// for (mask = 0x80; mask != 0; mask >>= 1)
+// {
+// if (bt & mask) strcat(buf, "#");
+// else strcat(buf, "-");
+// ++x;
+// if (x == cols) { strcat(buf, "\n"); x = 0; }
+// }
+// PGCLOG((buf));
+
+ if (n < sizeof(im1024->font[ch])) im1024->font[ch][n] = bt;
+ }
+ im1024->fontx[ch] = cols;
+ im1024->fonty[ch] = rows;
+}
+
+static void hndl_tsize(pgc_core_t *pgc)
+{
+ int16_t size;
+
+ if (!pgc_param_word(pgc, &size)) return;
+ PGCLOG(("TSIZE(%d)\n", size));
+
+ pgc->tsize = size << 16;
+}
+
+
+
+static void hndl_twrite(pgc_core_t *pgc)
+{
+ unsigned char count;
+ unsigned char mask;
+ unsigned char *row;
+ int x, y, wb, n;
+ im1024_t * im1024 = (im1024_t *)pgc;
+ int16_t x0 = pgc->x >> 16;
+ int16_t y0 = pgc->y >> 16;
+ unsigned char buf[256];
+/* unsigned char rbuf[256];*/
+
+ if (!pgc_param_byte(pgc, &count)) return;
+
+ for (n = 0; n < count; n++)
+ {
+ if (!pgc_param_byte(pgc, &buf[n])) return;
+ }
+ buf[count] = 0;
+/* for (n = 0; n <= count; n++)
+ {
+ if (isprint(buf[n]) || 0 == buf[n])
+ {
+ rbuf[n] = buf[n];
+ }
+ else rbuf[n] = '?';
+ }*/
+ pgc_sto_raster(pgc, &x0, &y0);
+ PGCLOG(("TWRITE (%d,%-*.*s) x0=%d y0=%d\n", count, count, count, rbuf, x0, y0));
+
+ for (n = 0; n < count; n++)
+ {
+ wb = (im1024->fontx[buf[n]] + 7) / 8;
+ PGCLOG(("ch=0x%02x w=%d h=%d wb=%d\n",
+ buf[n], im1024->fontx[buf[n]],
+ im1024->fonty[buf[n]], wb));
+ for (y = 0; y < im1024->fonty[buf[n]]; y++)
+ {
+ mask = 0x80;
+ row = &im1024->font[buf[n]][y * wb];
+ for (x = 0; x < im1024->fontx[buf[n]]; x++)
+ {
+/* rbuf[x] = (row[0] & mask) ? '#' : '-';*/
+ if (row[0] & mask) pgc_plot(pgc, x + x0, y0 - y);
+ mask = mask >> 1;
+ if (mask == 0) { mask = 0x80; ++row; }
+ }
+/* rbuf[x++] = '\n';
+ rbuf[x++] = 0;*/
+// PGCLOG((rbuf);
+ }
+ x0 += im1024->fontx[buf[n]];
+ }
+}
+
+
+
+static void hndl_txt88(pgc_core_t *pgc)
+{
+ unsigned char count;
+ unsigned char mask;
+ unsigned char *row;
+ int x, y, /*wb, */n;
+ int16_t x0 = pgc->x >> 16;
+ int16_t y0 = pgc->y >> 16;
+ unsigned char buf[256];
+/* unsigned char rbuf[256];*/
+
+ if (!pgc_param_byte(pgc, &count)) return;
+
+ for (n = 0; n < count; n++)
+ {
+ if (!pgc_param_byte(pgc, &buf[n])) return;
+ }
+ buf[count] = 0;
+/* for (n = 0; n <= count; n++)
+ {
+ if (isprint(buf[n]) || 0 == buf[n])
+ {
+ rbuf[n] = buf[n];
+ }
+ else rbuf[n] = '?';
+ }*/
+ pgc_sto_raster(pgc, &x0, &y0);
+ PGCLOG(("TXT88 (%d,%-*.*s) x0=%d y0=%d\n", count, count, count, rbuf, x0, y0));
+
+ for (n = 0; n < count; n++)
+ {
+/* wb = 2;*/
+ PGCLOG(("ch=0x%02x w=%d h=%d wb=%d\n", buf[n], 12, 18, wb));
+ for (y = 0; y < 18; y++)
+ {
+ mask = 0x80;
+ row = &fontdat12x18[buf[n]][y * 2];
+ for (x = 0; x < 12; x++)
+ {
+/* rbuf[x] = (row[0] & mask) ? '#' : '-';*/
+ if (row[0] & mask) pgc_plot(pgc, x + x0, y0 - y);
+ mask = mask >> 1;
+ if (mask == 0) { mask = 0x80; ++row; }
+ }
+/* rbuf[x++] = '\n';
+ rbuf[x++] = 0;*/
+// PGCLOG((rbuf);
+ }
+ x0 += 12;
+ }
+}
+
+
+
+
+static void hndl_imagew(pgc_core_t *pgc)
+{
+ int16_t row1, col1, col2;
+ uint8_t v1, v2;
+ int16_t vp_x1, vp_y1, vp_x2, vp_y2;
+
+ if (!pgc_param_word(pgc, &row1)) return;
+ if (!pgc_param_word(pgc, &col1)) return;
+ if (!pgc_param_word(pgc, &col2)) return;
+
+ /* IMAGEW already uses raster coordinates so there is no need to
+ * convert it */
+ PGCLOG(("IMAGEW (row=%d,col1=%d,col2=%d)\n", row1, col1, col2));
+
+ vp_x1 = pgc->vp_x1;
+ vp_y1 = pgc->vp_y1;
+ vp_x2 = pgc->vp_x2;
+ vp_y2 = pgc->vp_y2;
+ /* Disable clipping */
+ pgc->vp_x1 = 0;
+ pgc->vp_y1 = 0;
+ pgc->vp_x2 = pgc->maxw - 1;
+ pgc->vp_y2 = pgc->maxh - 1;
+
+ /* In ASCII mode, what is written is a stream of bytes */
+ if (pgc->ascii_mode)
+ {
+ while (col1 <= col2)
+ {
+ if (!pgc_param_byte(pgc, &v1)) return;
+ pgc_write_pixel(pgc, col1, row1, v1);
+ ++col1;
+ }
+ return;
+ }
+ else /* In hex mode, it's RLE compressed */
+ {
+ while (col1 <= col2)
+ {
+ if (!pgc_param_byte(pgc, &v1)) return;
+
+ if (v1 & 0x80) /* Literal run */
+ {
+ v1 -= 0x7F;
+ while (col1 <= col2 && v1 != 0)
+ {
+ if (!pgc_param_byte(pgc, &v2)) return;
+ pgc_write_pixel(pgc, col1, row1, v2);
+ ++col1;
+ --v1;
+ }
+ }
+ else /* Repeated run */
+ {
+ if (!pgc_param_byte(pgc, &v2)) return;
+
+ ++v1;
+ while (col1 <= col2 && v1 != 0)
+ {
+ pgc_write_pixel(pgc, col1, row1, v2);
+ ++col1;
+ --v1;
+ }
+ }
+ }
+ }
+ /* Restore clipping */
+ pgc->vp_x1 = vp_x1;
+ pgc->vp_y1 = vp_y1;
+ pgc->vp_x2 = vp_x2;
+ pgc->vp_y2 = vp_y2;
+}
+
+/* I have called this command DOT - I don't know its proper name. Draws a
+ * single pixel at the current location */
+static void hndl_dot(pgc_core_t *pgc)
+{
+ int16_t x = pgc->x >> 16, y = pgc->y >> 16;
+
+ pgc_sto_raster(pgc, &x, &y);
+
+ PGCLOG(("Dot @ %d,%d ink=%d mode=%d\n", x, y, pgc->colour, pgc->draw_mode));
+ pgc_plot(pgc, x, y);
+}
+
+/* This command (which I have called IMAGEX, since I don't know its real
+ * name) is a screen-to-memory blit. It reads a rectangle of bytes, rather
+ * than the single row read by IMAGER, and does not attempt to compress
+ * the result */
+static void hndl_imagex(pgc_core_t *pgc)
+{
+ int16_t x0, x1, y0, y1;
+ int16_t p,q;
+
+ if (!pgc_param_word(pgc, &x0)) return;
+ if (!pgc_param_word(pgc, &y0)) return;
+ if (!pgc_param_word(pgc, &x1)) return;
+ if (!pgc_param_word(pgc, &y1)) return;
+
+ /* IMAGEX already uses raster coordinates so don't convert */
+ PGCLOG(("IMAGEX (%d,%d,%d,%d)\n", x0,y0,x1,y1));
+
+ for (p = y0; p <= y1; p++)
+ {
+ for (q = x0; q <= x1; q++)
+ {
+ if (!pgc_result_byte(pgc, pgc_read_pixel(pgc, q, p)))
+ return;
+ }
+ }
+}
+
+/* Commands implemented by the IM-1024.
+ *
+ * TODO: A lot of commands need commandlist parsers.
+ * TODO: The IM-1024 has a lot more commands that are not included here
+ * (BLINK, BUTRD, COPROC, RBAND etc) because the Windows 1.03 driver
+ * does not use them.
+ */
+static const pgc_command_t im1024_commands[] =
+{
+ { "BLKMOV", 0xDF, hndl_blkmov, pgc_parse_words, 6 },
+ { "DRAW", 0x28, hndl_draw, pgc_parse_words, 2 },
+ { "D", 0x28, hndl_draw, pgc_parse_words, 2 },
+ { "DOT", 0x08, hndl_dot },
+ { "ELIPSE", 0x39, hndl_ellipse, pgc_parse_words, 2 },
+ { "EL", 0x39, hndl_ellipse, pgc_parse_words, 2 },
+ { "IMAGEW", 0xD9, hndl_imagew },
+ { "IW", 0xD9, hndl_imagew },
+ { "IMAGEX", 0xDA, hndl_imagex },
+ { "TXT88", 0x88, hndl_txt88 },
+ { "TWRITE", 0x8B, hndl_twrite },
+ { "TDEFIN", 0x84, hndl_tdefin },
+ { "TD", 0x84, hndl_tdefin },
+ { "TSIZE", 0x81, hndl_tsize },
+ { "TS", 0x81, hndl_tsize },
+ { "IPREC", 0xE4, hndl_iprec },
+ { "IMGSIZ", 0x4E, hndl_imgsiz },
+ { "LUT8", 0xE6, pgc_hndl_lut8 },
+ { "L8", 0xE6, pgc_hndl_lut8 },
+ { "LUT8RD", 0x53, pgc_hndl_lut8rd },
+ { "L8RD", 0x53, pgc_hndl_lut8rd },
+ { "PAN", 0xB7, hndl_pan },
+ { "POLY", 0x30, hndl_poly, parse_poly },
+ { "P", 0x30, hndl_poly, parse_poly },
+ { "PLINE", 0x36, hndl_pline },
+ { "PL", 0x37, hndl_pline },
+ { "MOVE", 0x10, hndl_move, pgc_parse_words, 2 },
+ { "M", 0x10, hndl_move, pgc_parse_words, 2 },
+ { "RECT", 0x34, hndl_rect },
+ { "R", 0x34, hndl_rect },
+ { "******", 0x00, NULL }
+};
+
+
+void *im1024_init()
+{
+ im1024_t *im1024 = malloc(sizeof(im1024_t));
+ memset(im1024, 0, sizeof(im1024_t));
+
+ im1024->fifo = malloc(4096);
+ im1024->fifo_len = 4096;
+ im1024->fifo_wrptr = 0;
+ im1024->fifo_rdptr = 0;
+
+ /* 1024x1024 framebuffer with 1024x800 visible
+ Pixel clock is a guess */
+ pgc_core_init(&im1024->pgc, 1024, 1024, 1024, 800, im1024_input_byte, 65000000.0);
+
+ mem_mapping_set_handler(&im1024->pgc.mapping,
+ im1024_read, NULL, NULL,
+ im1024_write, NULL, NULL);
+
+ im1024->pgc.pgc_commands = im1024_commands;
+ return im1024;
+}
+
+void im1024_close(void *p)
+{
+ im1024_t *im1024 = (im1024_t *)p;
+
+ pgc_close(&im1024->pgc);
+}
+
+void im1024_speed_changed(void *p)
+{
+ im1024_t *im1024 = (im1024_t *)p;
+
+ pgc_speed_changed(&im1024->pgc);
+}
+
+device_t im1024_device =
+{
+ "Image Manager 1024",
+ 0,
+ im1024_init,
+ im1024_close,
+ NULL,
+ im1024_speed_changed,
+ NULL,
+ NULL,
+ NULL
+};
diff --git a/src/vid_im1024.h b/src/vid_im1024.h
new file mode 100644
index 0000000..145401e
--- /dev/null
+++ b/src/vid_im1024.h
@@ -0,0 +1 @@
+extern device_t im1024_device;
diff --git a/src/vid_mda.c b/src/vid_mda.c
index c54aa85..31ba65a 100644
--- a/src/vid_mda.c
+++ b/src/vid_mda.c
@@ -8,29 +8,6 @@
#include "video.h"
#include "vid_mda.h"
-typedef struct mda_t
-{
- mem_mapping_t mapping;
-
- uint8_t crtc[32];
- int crtcreg;
-
- uint8_t ctrl, stat;
-
- uint64_t dispontime, dispofftime;
- pc_timer_t timer;
-
- int firstline, lastline;
-
- int linepos, displine;
- int vc, sc;
- uint16_t ma, maback;
- int con, coff, cursoron;
- int dispon, blink;
- int vsynctime, vadj;
-
- uint8_t *vram;
-} mda_t;
static uint32_t mdacols[256][2][2];
@@ -261,18 +238,25 @@ void mda_poll(void *p)
}
}
-void *mda_init()
+void *mda_standalone_init()
+{
+ mda_t *mda = malloc(sizeof(mda_t));
+
+ memset(mda, 0, sizeof(mda_t));
+ mda_init(mda);
+
+ mda->vram = malloc(0x1000);
+ mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, mda);
+ io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda);
+
+ return mda;
+}
+
+
+void mda_init(mda_t *mda)
{
int display_type;
int c;
- mda_t *mda = malloc(sizeof(mda_t));
- memset(mda, 0, sizeof(mda_t));
-
- mda->vram = malloc(0x1000);
-
- timer_add(&mda->timer, mda_poll, mda, 1);
- mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, mda);
- io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda);
display_type = device_get_config_int("display_type");
cgapal_rebuild(display_type, 0);
@@ -295,8 +279,13 @@ void *mda_init()
mdacols[0x08][0][1] = mdacols[0x08][1][1] = cgapal[0];
mdacols[0x80][0][1] = mdacols[0x80][1][1] = cgapal[0];
mdacols[0x88][0][1] = mdacols[0x88][1][1] = cgapal[0];
+
+ timer_add(&mda->timer, mda_poll, mda, 1);
+}
- return mda;
+void mda_setcol(int chr, int blink, int fg, uint8_t cga_ink)
+{
+ mdacols[chr][blink][fg] = cgapal[cga_ink];
}
void mda_close(void *p)
@@ -349,7 +338,7 @@ device_t mda_device =
{
"MDA",
0,
- mda_init,
+ mda_standalone_init,
mda_close,
NULL,
mda_speed_changed,
diff --git a/src/vid_mda.h b/src/vid_mda.h
index 99aa13c..7a5a2f7 100644
--- a/src/vid_mda.h
+++ b/src/vid_mda.h
@@ -1 +1,38 @@
+
+typedef struct mda_t
+{
+ mem_mapping_t mapping;
+
+ uint8_t crtc[32];
+ int crtcreg;
+
+ uint8_t ctrl, stat;
+
+ uint64_t dispontime, dispofftime;
+ pc_timer_t timer;
+
+ int firstline, lastline;
+
+ int linepos, displine;
+ int vc, sc;
+ uint16_t ma, maback;
+ int con, coff, cursoron;
+ int dispon, blink;
+ int vsynctime, vadj;
+
+ uint8_t *vram;
+} mda_t;
+
+void mda_init(mda_t *mda);
+void mda_out(uint16_t addr, uint8_t val, void *p);
+uint8_t mda_in(uint16_t addr, void *p);
+void mda_write(uint32_t addr, uint8_t val, void *p);
+uint8_t mda_read(uint32_t addr, void *p);
+void mda_recalctimings(mda_t *mda);
+void mda_poll(void *p);
+
+/* Override mapping of attribute to colour */
+void mda_setcol(int chr, int blink, int fg, uint8_t cga_ink);
+
extern device_t mda_device;
+
diff --git a/src/vid_mga.c b/src/vid_mga.c
new file mode 100644
index 0000000..4bcc091
--- /dev/null
+++ b/src/vid_mga.c
@@ -0,0 +1,5439 @@
+/*Matrox Mystique emulation*/
+#include
+#include "ibm.h"
+#include "device.h"
+#include "io.h"
+#include "mem.h"
+#include "pci.h"
+#include "rom.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_mga.h"
+#include "vid_svga.h"
+#include "vid_svga_render.h"
+
+#define FIFO_SIZE 65536
+#define FIFO_MASK (FIFO_SIZE - 1)
+#define FIFO_ENTRY_SIZE (1 << 31)
+#define FIFO_THRESHOLD 0xe000
+
+#define WAKE_DELAY (100 * TIMER_USEC) /*100us*/
+
+#define FIFO_ENTRIES (mystique->fifo_write_idx - mystique->fifo_read_idx)
+#define FIFO_FULL ((mystique->fifo_write_idx - mystique->fifo_read_idx) >= (FIFO_SIZE-1))
+#define FIFO_EMPTY (mystique->fifo_read_idx == mystique->fifo_write_idx)
+
+#define FIFO_TYPE 0xff000000
+#define FIFO_ADDR 0x00ffffff
+
+enum
+{
+ FIFO_INVALID = (0x00 << 24),
+ FIFO_WRITE_CTRL_BYTE = (0x01 << 24),
+ FIFO_WRITE_CTRL_LONG = (0x02 << 24),
+ FIFO_WRITE_ILOAD_LONG = (0x03 << 24)
+};
+
+typedef struct
+{
+ uint32_t addr_type;
+ uint32_t val;
+} fifo_entry_t;
+
+typedef struct mystique_t
+{
+ svga_t svga;
+
+ rom_t bios_rom;
+
+ mem_mapping_t lfb_mapping;
+ mem_mapping_t ctrl_mapping;
+ mem_mapping_t iload_mapping;
+
+ uint8_t pci_regs[256];
+ uint8_t int_line;
+ int card;
+
+ int vram_size;
+ uint32_t vram_mask, vram_mask_w, vram_mask_l;
+
+ uint32_t lfb_base, ctrl_base, iload_base;
+
+ uint8_t crtcext_regs[6];
+ int crtcext_idx;
+
+ uint8_t xreg_regs[256];
+ int xreg_idx;
+
+ uint32_t ma_latch_old;
+
+ uint32_t maccess, mctlwtst;
+ uint32_t maccess_running;
+
+ uint32_t status;
+
+ uint8_t xcurctrl;
+
+ uint8_t xsyspllm, xsysplln, xsyspllp;
+ struct
+ {
+ int m, n, p, s;
+ } xpixpll[3];
+
+ uint8_t xgenioctrl;
+ uint8_t xgeniodata;
+ uint8_t xmulctrl;
+ uint8_t xgenctrl;
+ uint8_t xmiscctrl;
+ uint8_t xpixclkctrl;
+ uint8_t xvrefctrl;
+ uint8_t xcolkeymskl, xcolkeymskh;
+ uint8_t xcolkeyl, xcolkeyh;
+ int xzoomctrl;
+ uint8_t xcrcbitsel;
+
+ uint8_t ien;
+
+ struct
+ {
+ uint8_t funcnt, stylelen;
+ int xoff, yoff;
+
+ uint16_t cxleft, cxright;
+ int16_t fxleft, fxright;
+ uint16_t length;
+
+ uint32_t dwgctrl;
+ uint32_t dwgctrl_running;
+ uint32_t bcol, fcol;
+ uint32_t pitch;
+ uint32_t plnwt;
+ uint32_t ybot;
+ uint32_t ydstorg;
+ uint32_t ytop;
+ int selline;
+
+ uint32_t src[4];
+ uint32_t ar[7];
+ uint32_t dr[16];
+
+ int pattern[8][8];
+
+ struct
+ {
+ int sdydxl;
+ int scanleft;
+ int sdxl;
+ int sdy;
+ int sdxr;
+ } sgn;
+
+ uint32_t tmr[9];
+ uint32_t texorg, texwidth, texheight;
+ uint32_t texctl, textrans;
+ uint32_t zorg;
+
+ int ydst;
+ uint32_t ydst_lin;
+
+ int length_cur;
+ int16_t xdst;
+ uint32_t src_addr;
+ uint32_t z_base;
+
+ int iload_rem_count;
+ uint32_t iload_rem_data;
+ int idump_end_of_line;
+
+ int words;
+
+ int ta_key, ta_mask;
+
+ int lastpix_r, lastpix_g, lastpix_b;
+
+ int highv_line;
+ uint32_t highv_data;
+
+ int beta;
+
+ int dither;
+
+ uint8_t dmamod;
+ } dwgreg;
+
+ struct
+ {
+ uint8_t r, g, b;
+ } lut[256];
+
+ struct
+ {
+ uint16_t pos_x, pos_y;
+ uint16_t addr;
+ uint32_t col[3];
+ } cursor;
+
+ uint8_t dmamod, dmadatasiz, dirdatasiz;
+ struct
+ {
+ uint32_t primaddress, primend;
+ uint32_t secaddress, secend;
+
+ int pri_pos, sec_pos, iload_pos;
+ uint32_t pri_header, sec_header, iload_header;
+
+ int pri_state, sec_state, iload_state;
+
+ int state;
+
+ mutex_t *lock;
+// pc_timer_t timer;
+ } dma;
+
+ uint8_t dmamap[16];
+
+ volatile int busy;
+ volatile int blitter_submit_refcount;
+ volatile int blitter_submit_dma_refcount;
+ volatile int blitter_complete_refcount;
+
+ volatile int endprdmasts_pending;
+ volatile int softrap_pending;
+ uint32_t softrap_pending_val;
+
+ pc_timer_t softrap_pending_timer;
+
+ uint64_t blitter_time;
+ uint64_t status_time;
+
+ int pixel_count, trap_count;
+
+ 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;
+
+ pc_timer_t wake_timer;
+} mystique_t;
+
+static void mystique_start_blit(mystique_t *mystique);
+static void mystique_update_irqs(mystique_t *mystique);
+
+static void wake_fifo_thread(mystique_t *mystique);
+static void wait_fifo_idle(mystique_t *mystique);
+static void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type);
+
+static uint8_t mystique_readb_linear(uint32_t addr, void *p);
+static uint16_t mystique_readw_linear(uint32_t addr, void *p);
+static uint32_t mystique_readl_linear(uint32_t addr, void *p);
+static void mystique_writeb_linear(uint32_t addr, uint8_t val, void *p);
+static void mystique_writew_linear(uint32_t addr, uint16_t val, void *p);
+static void mystique_writel_linear(uint32_t addr, uint32_t val, void *p);
+
+static const uint8_t trans_masks[16][16] =
+{
+ {
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ 1, 1, 1, 1,
+ 1, 1, 1, 1
+ },
+ {
+ 1, 0, 1, 0,
+ 0, 1, 0, 1,
+ 1, 0, 1, 0,
+ 0, 1, 0, 1
+ },
+ {
+ 0, 1, 0, 1,
+ 1, 0, 1, 0,
+ 0, 1, 0, 1,
+ 1, 0, 1, 0
+ },
+ {
+ 1, 0, 1, 0,
+ 0, 0, 0, 0,
+ 1, 0, 1, 0,
+ 0, 0, 0, 0
+ },
+ {
+ 0, 1, 0, 1,
+ 0, 0, 0, 0,
+ 0, 1, 0, 1,
+ 0, 0, 0, 0
+ },
+ {
+ 0, 0, 0, 0,
+ 1, 0, 1, 0,
+ 0, 0, 0, 0,
+ 1, 0, 1, 0
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 1, 0, 1,
+ 0, 0, 0, 0,
+ 0, 1, 0, 1
+ },
+ {
+ 1, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 0
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 1
+ },
+ {
+ 0, 0, 0, 1,
+ 0, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 0
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 0,
+ 1, 0, 0, 0
+ },
+ {
+ 0, 0, 0, 0,
+ 1, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 1, 0
+ },
+ {
+ 0, 1, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 1,
+ 0, 0, 0, 0
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 1,
+ 0, 0, 0, 0,
+ 0, 1, 0, 0
+ },
+ {
+ 0, 0, 1, 0,
+ 0, 0, 0, 0,
+ 1, 0, 0, 0,
+ 0, 0, 0, 0
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+ }
+};
+
+static int8_t dither5[256][2][2];
+static int8_t dither6[256][2][2];
+
+enum
+{
+ DMA_STATE_IDLE = 0,
+ DMA_STATE_PRI,
+ DMA_STATE_SEC
+};
+
+#define DMA_POLL_TIME_US 100 /*100us*/
+#define DMA_MAX_WORDS 256 /*256 quad words per 100us poll*/
+
+/*These registers are also mirrored into 0x1dxx, with the mirrored versions starting
+ the blitter*/
+#define REG_DWGCTL 0x1c00
+#define REG_MACCESS 0x1c04
+#define REG_MCTLWTST 0x1c08
+#define REG_ZORG 0x1c0c
+#define REG_PAT0 0x1c10
+#define REG_PAT1 0x1c14
+#define REG_PLNWT 0x1c1c
+#define REG_BCOL 0x1c20
+#define REG_FCOL 0x1c24
+#define REG_SRC0 0x1c30
+#define REG_SRC1 0x1c34
+#define REG_SRC2 0x1c38
+#define REG_SRC3 0x1c3c
+#define REG_XYSTRT 0x1c40
+#define REG_XYEND 0x1c44
+#define REG_SHIFT 0x1c50
+#define REG_DMAPAD 0x1c54
+#define REG_SGN 0x1c58
+#define REG_LEN 0x1c5c
+#define REG_AR0 0x1c60
+#define REG_AR1 0x1c64
+#define REG_AR2 0x1c68
+#define REG_AR3 0x1c6c
+#define REG_AR4 0x1c70
+#define REG_AR5 0x1c74
+#define REG_AR6 0x1c78
+#define REG_CXBNDRY 0x1c80
+#define REG_FXBNDRY 0x1c84
+#define REG_YDSTLEN 0x1c88
+#define REG_PITCH 0x1c8c
+#define REG_YDST 0x1c90
+#define REG_YDSTORG 0x1c94
+#define REG_YTOP 0x1c98
+#define REG_YBOT 0x1c9c
+#define REG_CXLEFT 0x1ca0
+#define REG_CXRIGHT 0x1ca4
+#define REG_FXLEFT 0x1ca8
+#define REG_FXRIGHT 0x1cac
+#define REG_XDST 0x1cb0
+#define REG_DR0 0x1cc0
+#define REG_DR2 0x1cc8
+#define REG_DR3 0x1ccc
+#define REG_DR4 0x1cd0
+#define REG_DR6 0x1cd8
+#define REG_DR7 0x1cdc
+#define REG_DR8 0x1ce0
+#define REG_DR10 0x1ce8
+#define REG_DR11 0x1cec
+#define REG_DR12 0x1cf0
+#define REG_DR14 0x1cf8
+#define REG_DR15 0x1cfc
+
+#define REG_FIFOSTATUS 0x1e10
+#define REG_STATUS 0x1e14
+#define REG_ICLEAR 0x1e18
+#define REG_IEN 0x1e1c
+#define REG_VCOUNT 0x1e20
+#define REG_DMAMAP 0x1e30
+#define REG_RST 0x1e40
+#define REG_OPMODE 0x1e54
+#define REG_PRIMADDRESS 0x1e58
+#define REG_PRIMEND 0x1e5c
+#define REG_DWG_INDIR_WT 0x1e80
+
+#define REG_ATTR_IDX 0x1fc0
+#define REG_ATTR_DATA 0x1fc1
+#define REG_INSTS0 0x1fc2
+#define REG_MISC 0x1fc2
+#define REG_SEQ_IDX 0x1fc4
+#define REG_SEQ_DATA 0x1fc5
+#define REG_MISCREAD 0x1fcc
+#define REG_GCTL_IDX 0x1fce
+#define REG_GCTL_DATA 0x1fcf
+#define REG_CRTC_IDX 0x1fd4
+#define REG_CRTC_DATA 0x1fd5
+#define REG_INSTS1 0x1fda
+#define REG_CRTCEXT_IDX 0x1fde
+#define REG_CRTCEXT_DATA 0x1fdf
+#define REG_CACHEFLUSH 0x1fff
+
+#define REG_TMR0 0x2c00
+#define REG_TMR1 0x2c04
+#define REG_TMR2 0x2c08
+#define REG_TMR3 0x2c0c
+#define REG_TMR4 0x2c10
+#define REG_TMR5 0x2c14
+#define REG_TMR6 0x2c18
+#define REG_TMR7 0x2c1c
+#define REG_TMR8 0x2c20
+#define REG_TEXORG 0x2c24
+#define REG_TEXWIDTH 0x2c28
+#define REG_TEXHEIGHT 0x2c2c
+#define REG_TEXCTL 0x2c30
+#define REG_TEXTRANS 0x2c34
+#define REG_SECADDRESS 0x2c40
+#define REG_SECEND 0x2c44
+#define REG_SOFTRAP 0x2c48
+
+#define REG_PALWTADD 0x3c00
+#define REG_PALDATA 0x3c01
+#define REG_PIXRDMSK 0x3c02
+#define REG_PALRDADD 0x3c03
+#define REG_X_DATAREG 0x3c0a
+#define REG_CURPOSX 0x3c0c
+#define REG_CURPOSY 0x3c0e
+
+#define REG_STATUS_VSYNCSTS (1 << 3)
+
+#define CRTCX_R0_STARTADD_MASK (0xf << 0)
+#define CRTCX_R0_OFFSET_MASK (3 << 4)
+
+#define CRTCX_R1_HTOTAL8 (1 << 0)
+
+#define CRTCX_R2_VTOTAL10 (1 << 0)
+#define CRTCX_R2_VTOTAL11 (1 << 1)
+#define CRTCX_R2_VDISPEND10 (1 << 2)
+#define CRTCX_R2_VBLKSTR10 (1 << 3)
+#define CRTCX_R2_VBLKSTR11 (1 << 4)
+#define CRTCX_R2_VSYNCSTR10 (1 << 5)
+#define CRTCX_R2_VSYNCSTR11 (1 << 6)
+#define CRTCX_R2_LINECOMP10 (1 << 7)
+
+#define CRTCX_R3_MGAMODE (1 << 7)
+
+#define XREG_XCURADDL 0x04
+#define XREG_XCURADDH 0x05
+#define XREG_XCURCTRL 0x06
+
+#define XREG_XCURCOL0R 0x08
+#define XREG_XCURCOL0G 0x09
+#define XREG_XCURCOL0B 0x0a
+
+#define XREG_XCURCOL1R 0x0c
+#define XREG_XCURCOL1G 0x0d
+#define XREG_XCURCOL1B 0x0e
+
+#define XREG_XCURCOL2R 0x10
+#define XREG_XCURCOL2G 0x11
+#define XREG_XCURCOL2B 0x12
+
+#define XREG_XVREFCTRL 0x18
+#define XREG_XMULCTRL 0x19
+#define XREG_XPIXCLKCTRL 0x1a
+#define XREG_XGENCTRL 0x1d
+#define XREG_XMISCCTRL 0x1e
+
+#define XREG_XGENIOCTRL 0x2a
+#define XREG_XGENIODATA 0x2b
+
+#define XREG_XSYSPLLM 0x2c
+#define XREG_XSYSPLLN 0x2d
+#define XREG_XSYSPLLP 0x2e
+#define XREG_XSYSPLLSTAT 0x2f
+
+#define XREG_XZOOMCTRL 0x38
+
+#define XREG_XSENSETEST 0x3a
+
+#define XREG_XCRCREML 0x3c
+#define XREG_XCRCREMH 0x3d
+#define XREG_XCRCBITSEL 0x3e
+
+#define XREG_XCOLKEYMSKL 0x40
+#define XREG_XCOLKEYMSKH 0x41
+#define XREG_XCOLKEYL 0x42
+#define XREG_XCOLKEYH 0x43
+
+#define XREG_XPIXPLLCM 0x4c
+#define XREG_XPIXPLLCN 0x4d
+#define XREG_XPIXPLLCP 0x4e
+#define XREG_XPIXPLLSTAT 0x4f
+
+#define XMISCCTRL_VGA8DAC (1 << 3)
+
+#define XMULCTRL_DEPTH_MASK (7 << 0)
+#define XMULCTRL_DEPTH_8 (0 << 0)
+#define XMULCTRL_DEPTH_15 (1 << 0)
+#define XMULCTRL_DEPTH_16 (2 << 0)
+#define XMULCTRL_DEPTH_24 (3 << 0)
+#define XMULCTRL_DEPTH_32_OVERLAYED (4 << 0)
+#define XMULCTRL_DEPTH_2G8V16 (5 << 0)
+#define XMULCTRL_DEPTH_G16V16 (6 << 0)
+#define XMULCTRL_DEPTH_32 (7 << 0)
+
+#define XSYSPLLSTAT_SYSLOCK (1 << 6)
+
+#define XPIXPLLSTAT_SYSLOCK (1 << 6)
+
+#define XCURCTRL_CURMODE_MASK (3 << 0)
+#define XCURCTRL_CURMODE_3COL (1 << 0)
+#define XCURCTRL_CURMODE_XGA (2 << 0)
+#define XCURCTRL_CURMODE_XWIN (3 << 0)
+
+#define DWGCTRL_OPCODE_MASK (0xf << 0)
+#define DWGCTRL_OPCODE_LINE_OPEN (0x0 << 0)
+#define DWGCTRL_OPCODE_AUTOLINE_OPEN (0x1 << 0)
+#define DWGCTRL_OPCODE_AUTOLINE_CLOSE (0x3 << 0)
+#define DWGCTRL_OPCODE_TRAP (0x4 << 0)
+#define DWGCTRL_OPCODE_TEXTURE_TRAP (0x6 << 0)
+#define DWGCTRL_OPCODE_ILOAD_HIGH (0x7 << 0)
+#define DWGCTRL_OPCODE_BITBLT (0x8 << 0)
+#define DWGCTRL_OPCODE_ILOAD (0x9 << 0)
+#define DWGCTRL_OPCODE_IDUMP (0xa << 0)
+#define DWGCTRL_OPCODE_ILOAD_SCALE (0xd << 0)
+#define DWGCTRL_OPCODE_ILOAD_HIGHV (0xe << 0)
+#define DWGCTRL_ATYPE_MASK (7 << 4)
+#define DWGCTRL_ATYPE_RPL (0 << 4)
+#define DWGCTRL_ATYPE_RSTR (1 << 4)
+#define DWGCTRL_ATYPE_ZI (3 << 4)
+#define DWGCTRL_ATYPE_BLK (4 << 4)
+#define DWGCTRL_ATYPE_I (7 << 4)
+#define DWGCTRL_LINEAR (1 << 7)
+#define DWGCTRL_ZMODE_MASK (7 << 8)
+#define DWGCTRL_ZMODE_NOZCMP (0 << 8)
+#define DWGCTRL_ZMODE_ZE (2 << 8)
+#define DWGCTRL_ZMODE_ZNE (3 << 8)
+#define DWGCTRL_ZMODE_ZLT (4 << 8)
+#define DWGCTRL_ZMODE_ZLTE (5 << 8)
+#define DWGCTRL_ZMODE_ZGT (6 << 8)
+#define DWGCTRL_ZMODE_ZGTE (7 << 8)
+#define DWGCTRL_SOLID (1 << 11)
+#define DWGCTRL_ARZERO (1 << 12)
+#define DWGCTRL_SGNZERO (1 << 13)
+#define DWGCTRL_SHTZERO (1 << 14)
+#define DWGCTRL_BOP_MASK (0xf << 16)
+#define DWGCTRL_TRANS_SHIFT (20)
+#define DWGCTRL_TRANS_MASK (0xf << DWGCTRL_TRANS_SHIFT)
+#define DWGCTRL_BLTMOD_MASK (0xf << 25)
+#define DWGCTRL_BLTMOD_BMONOLEF (0x0 << 25)
+#define DWGCTRL_BLTMOD_BFCOL (0x2 << 25)
+#define DWGCTRL_BLTMOD_BMONOWF (0x4 << 25)
+#define DWGCTRL_BLTMOD_BU32RGB (0x7 << 25)
+#define DWGCTRL_BLTMOD_BUYUV (0xe << 25)
+#define DWGCTRL_BLTMOD_BU24RGB (0xf << 25)
+#define DWGCTRL_PATTERN (1 << 29)
+#define DWGCTRL_TRANSC (1 << 30)
+#define BOP(x) ((x) << 16)
+
+#define MACCESS_PWIDTH_MASK (3 << 0)
+#define MACCESS_PWIDTH_8 (0 << 0)
+#define MACCESS_PWIDTH_16 (1 << 0)
+#define MACCESS_PWIDTH_32 (2 << 0)
+#define MACCESS_PWIDTH_24 (3 << 0)
+#define MACCESS_TLUTLOAD (1 << 29)
+#define MACCESS_NODITHER (1 << 30)
+#define MACCESS_DIT555 (1 << 31)
+
+#define PITCH_MASK 0x7e0
+#define PITCH_YLIN (1 << 15)
+
+#define SGN_SDYDXL (1 << 0)
+#define SGN_SCANLEFT (1 << 0)
+#define SGN_SDXL (1 << 1)
+#define SGN_SDY (1 << 2)
+#define SGN_SDXR (1 << 5)
+
+#define DMA_ADDR_MASK 0xfffffffc
+#define DMA_MODE_MASK 3
+
+#define DMA_MODE_REG 0
+#define DMA_MODE_BLIT 1
+#define DMA_MODE_VECTOR 2
+
+#define STATUS_SOFTRAPEN (1 << 0)
+#define STATUS_VSYNCPEN (1 << 4)
+#define STATUS_VLINEPEN (1 << 5)
+#define STATUS_DWGENGSTS (1 << 16)
+#define STATUS_ENDPRDMASTS (1 << 17)
+
+#define ICLEAR_SOFTRAPICLR (1 << 0)
+#define ICLEAR_VLINEICLR (1 << 5)
+
+#define IEN_SOFTRAPEN (1 << 0)
+
+#define TEXCTL_TEXFORMAT_MASK (7 << 0)
+#define TEXCTL_TEXFORMAT_TW4 (0 << 0)
+#define TEXCTL_TEXFORMAT_TW8 (1 << 0)
+#define TEXCTL_TEXFORMAT_TW15 (2 << 0)
+#define TEXCTL_TEXFORMAT_TW16 (3 << 0)
+#define TEXCTL_TEXFORMAT_TW12 (4 << 0)
+#define TEXCTL_PALSEL_MASK (0xf << 4)
+#define TEXCTL_TPITCH_SHIFT (16)
+#define TEXCTL_TPITCH_MASK (7 << TEXCTL_TPITCH_SHIFT)
+#define TEXCTL_NPCEN (1 << 21)
+#define TEXCTL_DECALCKEY (1 << 24)
+#define TEXCTL_TAKEY (1 << 25)
+#define TEXCTL_TAMASK (1 << 26)
+#define TEXCTL_CLAMPV (1 << 27)
+#define TEXCTL_CLAMPU (1 << 28)
+#define TEXCTL_TMODULATE (1 << 29)
+#define TEXCTL_STRANS (1 << 30)
+#define TEXCTL_ITRANS (1 << 31)
+
+#define TEXHEIGHT_TH_MASK (0x3f << 0)
+#define TEXHEIGHT_THMASK_SHIFT (18)
+#define TEXHEIGHT_THMASK_MASK (0x7ff << TEXHEIGHT_THMASK_SHIFT)
+
+#define TEXWIDTH_TW_MASK (0x3f << 0)
+#define TEXWIDTH_TWMASK_SHIFT (18)
+#define TEXWIDTH_TWMASK_MASK (0x7ff << TEXWIDTH_TWMASK_SHIFT)
+
+#define TEXTRANS_TCKEY_MASK (0xffff)
+#define TEXTRANS_TKMASK_SHIFT (16)
+#define TEXTRANS_TKMASK_MASK (0xffff << TEXTRANS_TKMASK_SHIFT)
+
+#define DITHER_565 0
+#define DITHER_NONE_565 1
+#define DITHER_555 2
+#define DITHER_NONE_555 3
+
+static void mystique_recalc_mapping(mystique_t *mystique);
+static int mystique_line_compare(svga_t *svga);
+
+static uint8_t mystique_iload_read_b(uint32_t addr, void *p);
+static uint32_t mystique_iload_read_l(uint32_t addr, void *p);
+static void mystique_iload_write_b(uint32_t addr, uint8_t val, void *p);
+static void mystique_iload_write_l(uint32_t addr, uint32_t val, void *p);
+
+static uint32_t blit_idump_read(mystique_t *mystique);
+static void blit_iload_write(mystique_t *mystique, uint32_t data, int size);
+
+void mystique_out(uint16_t addr, uint8_t val, void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+ svga_t *svga = &mystique->svga;
+ uint8_t old;
+
+ if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) addr ^= 0x60; // mono / color addr selection
+
+// pclog("mystique_out : %04X %02X\n", addr, val);
+// pclog(" %04X:%04X\n", CS,cpu_state.pc);
+ switch (addr)
+ {
+ case 0x3c8:
+ mystique->xreg_idx = val;
+ break;
+
+ case 0x3cf:
+ if ((svga->gdcaddr & 15) == 6 && svga->gdcreg[6] != val)
+ {
+ svga->gdcreg[svga->gdcaddr & 15] = val;
+ mystique_recalc_mapping(mystique);
+ return;
+ }
+ break;
+
+ case 0x3D4:
+ svga->crtcreg = val & 0x3f;
+ return;
+ case 0x3D5:
+// if (svga->crtcreg == 0xc)
+// pclog("Buffer swap\n");
+ if (((svga->crtcreg & 0x3f) < 7) && (svga->crtc[0x11] & 0x80))
+ return;
+ if (((svga->crtcreg & 0x3f) == 7) && (svga->crtc[0x11] & 0x80))
+ val = (svga->crtc[7] & ~0x10) | (val & 0x10);
+ old = svga->crtc[svga->crtcreg & 0x3f];
+ svga->crtc[svga->crtcreg & 0x3f] = val;
+ if (old != val)
+ {
+ if ((svga->crtcreg & 0x3f) < 0xE || (svga->crtcreg & 0x3f) > 0x10)
+ {
+ svga->fullchange = changeframecount;
+ svga_recalctimings(svga);
+ }
+ if (svga->crtcreg == 0x11)
+ {
+ if (!(val & 0x10))
+ mystique->status &= ~STATUS_VSYNCPEN;
+ mystique_update_irqs(mystique);
+ }
+ }
+ break;
+
+ case 0x3de:
+ mystique->crtcext_idx = val;
+ break;
+ case 0x3df:
+ if (mystique->crtcext_idx < 6)
+ mystique->crtcext_regs[mystique->crtcext_idx] = val;
+ if (mystique->crtcext_idx < 4)
+ {
+ svga->fullchange = changeframecount;
+ svga_recalctimings(svga);
+ }
+ if (mystique->crtcext_idx == 3)
+ {
+ if (val & CRTCX_R3_MGAMODE)
+ svga->fb_only = 1;
+ else
+ svga->fb_only = 0;
+ svga_recalctimings(svga);
+
+// pclog("Write CRTCX[3]=%02x\n", val);
+ }
+ if (mystique->crtcext_idx == 4)
+ {
+ if (svga->gdcreg[6] & 0xc)
+ {
+ /*64k banks*/
+ svga->read_bank = (val & 0x7f) << 16;
+ svga->write_bank = (val & 0x7f) << 16;
+ }
+ else
+ {
+ /*128k banks*/
+ svga->read_bank = (val & 0x7e) << 16;
+ svga->write_bank = (val & 0x7e) << 16;
+ }
+// pclog("Write CRTCX[4]=%02x %08x\n", val, svga->read_bank);
+ }
+ break;
+
+ }
+ svga_out(addr, val, svga);
+}
+
+uint8_t mystique_in(uint16_t addr, void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+ svga_t *svga = &mystique->svga;
+ uint8_t temp = 0xff;
+
+ if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) addr ^= 0x60; // mono / color addr selection
+
+// if (addr != 0x3da && addr != 0x3ba) pclog("mystique_in : %04X ", addr);
+
+ switch (addr)
+ {
+ case 0x3D4:
+ temp = svga->crtcreg;
+ break;
+ case 0x3D5:
+ temp = svga->crtc[svga->crtcreg & 0x3f];
+ break;
+
+ case 0x3df:
+ if (mystique->crtcext_idx < 6)
+ temp = mystique->crtcext_regs[mystique->crtcext_idx];
+ break;
+
+ default:
+ temp = svga_in(addr, svga);
+ break;
+ }
+
+// if (addr != 0x3da && addr != 0x3ba) pclog("%02X\n", temp);
+ return temp;
+}
+
+static int mystique_line_compare(svga_t *svga)
+{
+ mystique_t *mystique = (mystique_t *)svga->p;
+
+ mystique->status |= STATUS_VLINEPEN;
+ mystique_update_irqs(mystique);
+
+ return 0;
+}
+
+static void mystique_vsync_callback(svga_t *svga)
+{
+ mystique_t *mystique = (mystique_t *)svga->p;
+
+ if (svga->crtc[0x11] & 0x10)
+ {
+ mystique->status |= STATUS_VSYNCPEN;
+ mystique_update_irqs(mystique);
+ }
+
+}
+
+void mystique_recalctimings(svga_t *svga)
+{
+ mystique_t *mystique = (mystique_t *)svga->p;
+ int clk_sel = (svga->miscout >> 2) & 3;
+
+ if (clk_sel & 2)
+ {
+ int m = mystique->xpixpll[2].m;
+ int n = mystique->xpixpll[2].n;
+ int p = mystique->xpixpll[2].p;
+
+ double fvco = 14318181.0 * (n + 1) / (m + 1);
+ double fo = fvco / (p + 1);
+
+// pclog("m=%i n=%i p=%i fo=%g\n", m, n, p, fo);
+ svga->clock = (cpuclock * (float)(1ull << 32)) / fo;
+ }
+
+ if (mystique->crtcext_regs[1] & CRTCX_R1_HTOTAL8)
+ svga->htotal += 0x100;
+ if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10)
+ svga->vtotal += 0x400;
+ if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL11)
+ svga->vtotal += 0x800;
+ if (mystique->crtcext_regs[2] & CRTCX_R2_VDISPEND10)
+ svga->dispend += 0x400;
+ if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR10)
+ svga->vblankstart += 0x400;
+ if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR11)
+ svga->vblankstart += 0x800;
+ if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR10)
+ svga->vsyncstart += 0x400;
+ if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR11)
+ svga->vsyncstart += 0x800;
+ if (mystique->crtcext_regs[2] & CRTCX_R2_LINECOMP10)
+ svga->split += 0x400;
+// pclog("svga->split=%i\n", svga->split);
+
+ if (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE)
+ {
+ int row_offset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4);
+
+// svga->split = 99999;
+ svga->lowres = 0;
+ svga->char_width = 8;
+ svga->hdisp = (svga->crtc[1] + 1) * 8;
+ svga->hdisp_time = svga->hdisp;
+ svga->rowoffset = row_offset * 2;
+ svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 17) |
+ (svga->crtc[0xc] << 9) | (svga->crtc[0xd] << 1);
+
+ /*Mystique, unlike most SVGA cards, allows display start to take
+ effect mid-screen*/
+ if (svga->ma_latch != mystique->ma_latch_old)
+ {
+// pclog("ma_latch change: old=%08x new=%08x ma=%08x ", mystique->ma_latch_old, svga->ma_latch, svga->maback);
+ svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2);
+// pclog("ma_new=%08x\n", svga->maback);
+ mystique->ma_latch_old = svga->ma_latch;
+ }
+
+ switch (mystique->xmulctrl & XMULCTRL_DEPTH_MASK)
+ {
+ case XMULCTRL_DEPTH_8:
+ case XMULCTRL_DEPTH_2G8V16:
+ svga->render = svga_render_8bpp_highres;
+ svga->bpp = 8;
+ break;
+ case XMULCTRL_DEPTH_15:
+ case XMULCTRL_DEPTH_G16V16:
+ svga->render = svga_render_15bpp_highres;
+ svga->bpp = 15;
+ break;
+ case XMULCTRL_DEPTH_16:
+ svga->render = svga_render_16bpp_highres;
+ svga->bpp = 15;
+ break;
+ case XMULCTRL_DEPTH_24:
+ svga->render = svga_render_24bpp_highres;
+ svga->bpp = 24;
+ break;
+ case XMULCTRL_DEPTH_32:
+ case XMULCTRL_DEPTH_32_OVERLAYED:
+ svga->render = svga_render_32bpp_highres;
+ svga->bpp = 32;
+ break;
+ }
+
+ svga->line_compare = mystique_line_compare;
+// pclog("recalc: htotal=%i vtotal=%i dispend=%i\n", svga->htotal, svga->vtotal, svga->dispend);
+
+ mem_mapping_set_handler(&mystique->lfb_mapping,
+ mystique_readb_linear, mystique_readw_linear, mystique_readl_linear,
+ mystique_writeb_linear, mystique_writew_linear, mystique_writel_linear);
+ }
+ else
+ {
+ svga->line_compare = NULL;
+ svga->bpp = 8;
+
+ mem_mapping_set_handler(&mystique->lfb_mapping,
+ svga_read_linear, svga_readw_linear, svga_readl_linear,
+ svga_write_linear, svga_writew_linear, svga_writel_linear);
+ }
+}
+
+static void mystique_recalc_mapping(mystique_t *mystique)
+{
+ svga_t *svga = &mystique->svga;
+
+ io_removehandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique);
+ if ((mystique->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && (mystique->pci_regs[0x41] & 1))
+ io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique);
+
+ if (!(mystique->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))
+ {
+ mem_mapping_disable(&svga->mapping);
+ mem_mapping_disable(&mystique->ctrl_mapping);
+ mem_mapping_disable(&mystique->lfb_mapping);
+ mem_mapping_disable(&mystique->iload_mapping);
+ return;
+ }
+
+ if (mystique->ctrl_base)
+ mem_mapping_set_addr(&mystique->ctrl_mapping, mystique->ctrl_base, 0x4000);
+ else
+ mem_mapping_disable(&mystique->ctrl_mapping);
+ if (mystique->lfb_base)
+ mem_mapping_set_addr(&mystique->lfb_mapping, mystique->lfb_base, 0x800000);
+ else
+ mem_mapping_disable(&mystique->lfb_mapping);
+ if (mystique->iload_base)
+ mem_mapping_set_addr(&mystique->iload_mapping, mystique->iload_base, 0x800000);
+ else
+ mem_mapping_disable(&mystique->iload_mapping);
+
+ if (mystique->pci_regs[0x41] & 1)
+ {
+ switch (svga->gdcreg[6] & 0x0C)
+ {
+ case 0x0: /*128k at A0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
+ svga->banked_mask = 0x1ffff;
+ 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;
+ }
+ if (svga->gdcreg[6] & 0xc)
+ {
+ /*64k banks*/
+ svga->read_bank = (mystique->crtcext_regs[4] & 0x7f) << 16;
+ svga->write_bank = (mystique->crtcext_regs[4] & 0x7f) << 16;
+ }
+ else
+ {
+ /*128k banks*/
+ svga->read_bank = (mystique->crtcext_regs[4] & 0x7e) << 16;
+ svga->write_bank = (mystique->crtcext_regs[4] & 0x7e) << 16;
+ }
+ }
+ else
+ mem_mapping_disable(&svga->mapping);
+}
+
+static void mystique_update_irqs(mystique_t *mystique)
+{
+ svga_t *svga = &mystique->svga;
+ int irq = 0;
+
+ if ((mystique->status & mystique->ien) & STATUS_SOFTRAPEN)
+ irq = 1;
+ if ((mystique->status & STATUS_VSYNCPEN) && (svga->crtc[0x11] & 0x30) == 0x10)
+ irq = 1;
+
+ if (irq)
+ pci_set_irq(mystique->card, PCI_INTA);
+ else
+ pci_clear_irq(mystique->card, PCI_INTA);
+}
+
+#define READ8(addr, var) switch ((addr) & 3) \
+ { \
+ case 0: ret = (var) & 0xff; break; \
+ case 1: ret = ((var) >> 8) & 0xff; break; \
+ case 2: ret = ((var) >> 16) & 0xff; break; \
+ case 3: ret = ((var) >> 24) & 0xff; break; \
+ }
+
+#define WRITE8(addr, var, val) switch ((addr) & 3) \
+ { \
+ case 0: var = (var & 0xffffff00) | (val); break; \
+ case 1: var = (var & 0xffff00ff) | ((val) << 8); break; \
+ case 2: var = (var & 0xff00ffff) | ((val) << 16); break; \
+ case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \
+ }
+
+static uint8_t mystique_read_xreg(mystique_t *mystique, int reg)
+{
+ uint8_t ret = 0xff;
+
+ switch (reg)
+ {
+ case XREG_XCURADDL:
+ ret = mystique->cursor.addr & 0xff;
+ break;
+ case XREG_XCURADDH:
+ ret = mystique->cursor.addr >> 8;
+ break;
+ case XREG_XCURCTRL:
+ ret = mystique->xcurctrl;
+ break;
+
+ case XREG_XCURCOL0R: case XREG_XCURCOL0G: case XREG_XCURCOL0B:
+ READ8(reg, mystique->cursor.col[0]);
+ break;
+ case XREG_XCURCOL1R: case XREG_XCURCOL1G: case XREG_XCURCOL1B:
+ READ8(reg, mystique->cursor.col[1]);
+ break;
+ case XREG_XCURCOL2R: case XREG_XCURCOL2G: case XREG_XCURCOL2B:
+ READ8(reg, mystique->cursor.col[2]);
+ break;
+
+ case XREG_XMULCTRL:
+ ret = mystique->xmulctrl;
+ break;
+
+ case XREG_XMISCCTRL:
+ ret = mystique->xmiscctrl;
+ break;
+
+ case XREG_XGENCTRL:
+ ret = mystique->xgenctrl;
+ break;
+
+ case XREG_XVREFCTRL:
+ ret = mystique->xvrefctrl;
+ break;
+
+ case XREG_XGENIOCTRL:
+ ret = mystique->xgenioctrl;
+ break;
+ case XREG_XGENIODATA:
+ ret = mystique->xgeniodata;
+ break;
+
+ case XREG_XSYSPLLM:
+ ret = mystique->xsyspllm;
+ break;
+ case XREG_XSYSPLLN:
+ ret = mystique->xsysplln;
+ break;
+ case XREG_XSYSPLLP:
+ ret = mystique->xsyspllp;
+ break;
+
+ case XREG_XZOOMCTRL:
+ ret = mystique->xzoomctrl;
+ break;
+
+ case XREG_XSENSETEST:
+ ret = 0;
+ if (mystique->svga.vgapal[0].b < 0x80)
+ ret |= 1;
+ if (mystique->svga.vgapal[0].g < 0x80)
+ ret |= 2;
+ if (mystique->svga.vgapal[0].r < 0x80)
+ ret |= 4;
+ break;
+
+ case XREG_XCRCREML: /*CRC not implemented*/
+ ret = 0;
+ break;
+ case XREG_XCRCREMH:
+ ret = 0;
+ break;
+ case XREG_XCRCBITSEL:
+ ret = mystique->xcrcbitsel;
+ break;
+
+ case XREG_XCOLKEYMSKL:
+ ret = mystique->xcolkeymskl;
+ break;
+ case XREG_XCOLKEYMSKH:
+ ret = mystique->xcolkeymskh;
+ break;
+ case XREG_XCOLKEYL:
+ ret = mystique->xcolkeyl;
+ break;
+ case XREG_XCOLKEYH:
+ ret = mystique->xcolkeyh;
+ break;
+
+ case XREG_XPIXCLKCTRL:
+ ret = mystique->xpixclkctrl;
+ break;
+
+ case XREG_XSYSPLLSTAT:
+ ret = XSYSPLLSTAT_SYSLOCK;
+ break;
+
+ case XREG_XPIXPLLSTAT:
+ ret = XPIXPLLSTAT_SYSLOCK;
+ break;
+
+ case XREG_XPIXPLLCM:
+ ret = mystique->xpixpll[2].m;
+ break;
+ case XREG_XPIXPLLCN:
+ ret = mystique->xpixpll[2].n;
+ break;
+ case XREG_XPIXPLLCP:
+ ret = mystique->xpixpll[2].p | (mystique->xpixpll[2].s << 3);
+ break;
+
+ case 0x00: case 0x20: case 0x3f:
+ ret = 0xff;
+ break;
+
+ default:
+ if (reg >= 0x50)
+ ret = 0xff;
+ else
+ fatal("Read XREG %02x\n", reg);
+ break;
+ }
+ return ret;
+}
+
+static void mystique_write_xreg(mystique_t *mystique, int reg, uint8_t val)
+{
+ svga_t *svga = &mystique->svga;
+
+ switch (reg)
+ {
+ case XREG_XCURADDL:
+ mystique->cursor.addr = (mystique->cursor.addr & 0x1f00) | val;
+ svga->hwcursor.addr = mystique->cursor.addr << 10;
+ break;
+ case XREG_XCURADDH:
+ mystique->cursor.addr = (mystique->cursor.addr & 0x00ff) | ((val & 0x1f) << 8);
+ svga->hwcursor.addr = mystique->cursor.addr << 10;
+ break;
+
+ case XREG_XCURCTRL:
+ mystique->xcurctrl = val;
+ svga->hwcursor.ena = (val & 3) ? 1 : 0;
+ break;
+
+ case XREG_XCURCOL0R: case XREG_XCURCOL0G: case XREG_XCURCOL0B:
+ WRITE8(reg, mystique->cursor.col[0], val);
+ break;
+ case XREG_XCURCOL1R: case XREG_XCURCOL1G: case XREG_XCURCOL1B:
+ WRITE8(reg, mystique->cursor.col[1], val);
+ break;
+ case XREG_XCURCOL2R: case XREG_XCURCOL2G: case XREG_XCURCOL2B:
+ WRITE8(reg, mystique->cursor.col[2], val);
+ break;
+
+ case XREG_XMULCTRL:
+ mystique->xmulctrl = val;
+ break;
+
+ case XREG_XMISCCTRL:
+ mystique->xmiscctrl = val;
+ svga_set_ramdac_type(svga, (val & XMISCCTRL_VGA8DAC) ? RAMDAC_8BIT : RAMDAC_6BIT);
+ break;
+
+ case XREG_XGENCTRL:
+ mystique->xgenctrl = val;
+ break;
+
+ case XREG_XVREFCTRL:
+ mystique->xvrefctrl = val;
+ break;
+
+ case XREG_XGENIOCTRL:
+ mystique->xgenioctrl = val;
+ break;
+ case XREG_XGENIODATA:
+ mystique->xgeniodata = val;
+ break;
+
+ case XREG_XSYSPLLM:
+ mystique->xsyspllm = val;
+ break;
+ case XREG_XSYSPLLN:
+ mystique->xsysplln = val;
+ break;
+ case XREG_XSYSPLLP:
+ mystique->xsyspllp = val;
+ break;
+
+ case XREG_XZOOMCTRL:
+ mystique->xzoomctrl = val & 3;
+ break;
+
+ case XREG_XSENSETEST:
+ break;
+
+ case XREG_XCRCREML: /*CRC not implemented*/
+ break;
+ case XREG_XCRCREMH:
+ break;
+ case XREG_XCRCBITSEL:
+ mystique->xcrcbitsel = val & 0x1f;
+ break;
+
+ case XREG_XCOLKEYMSKL:
+ mystique->xcolkeymskl = val;
+ break;
+ case XREG_XCOLKEYMSKH:
+ mystique->xcolkeymskh = val;
+ break;
+ case XREG_XCOLKEYL:
+ mystique->xcolkeyl = val;
+ break;
+ case XREG_XCOLKEYH:
+ mystique->xcolkeyh = val;
+ break;
+
+ case XREG_XSYSPLLSTAT:
+ break;
+
+ case XREG_XPIXPLLSTAT:
+ break;
+
+ case XREG_XPIXCLKCTRL:
+ mystique->xpixclkctrl = val;
+ break;
+
+ case XREG_XPIXPLLCM:
+ mystique->xpixpll[2].m = val;
+ break;
+ case XREG_XPIXPLLCN:
+ mystique->xpixpll[2].n = val;
+ break;
+ case XREG_XPIXPLLCP:
+ mystique->xpixpll[2].p = val & 7;
+ mystique->xpixpll[2].s = (val >> 3) & 3;
+ break;
+
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x07: case 0x0b: case 0x0f:
+ case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x1b: case 0x1c: case 0x20: case 0x39: case 0x3b: case 0x3f:
+ case 0x47: case 0x4b:
+ break;
+
+ default:
+ if (reg < 0x50)
+ fatal("Write XREG %02x %02x\n", reg, val);
+ break;
+ }
+}
+
+static uint8_t mystique_ctrl_read_b(uint32_t addr, void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+ svga_t *svga = &mystique->svga;
+ uint8_t ret = 0xff;
+ int fifocount;
+
+// pclog("mystique read %04x %08x\n", addr & 0x3fff, cpu_state.pc);
+
+ switch (addr & 0x3fff)
+ {
+ case REG_FIFOSTATUS:
+ fifocount = FIFO_SIZE - FIFO_ENTRIES;
+ if (fifocount > 64)
+ fifocount = 64;
+ ret = fifocount;
+ break;
+ case REG_FIFOSTATUS+1:
+ if (FIFO_EMPTY)
+ ret |= 2;
+ else if (FIFO_ENTRIES >= 64)
+ ret |= 1;
+// ret = 2; /*Empty*/
+ break;
+ case REG_FIFOSTATUS+2: case REG_FIFOSTATUS+3:
+ ret = 0;
+ break;
+
+ case REG_STATUS:
+ ret = mystique->status & 0xff;
+ if (svga->cgastat & 8)
+ ret |= REG_STATUS_VSYNCSTS;
+// pclog("REG_STATUS %02x\n", ret);
+ break;
+ case REG_STATUS+1:
+ ret = (mystique->status >> 8) & 0xff;
+ break;
+ case REG_STATUS+2:
+ ret = (mystique->status >> 16) & 0xff;
+ if (mystique->busy ||
+ ((mystique->blitter_submit_refcount + mystique->blitter_submit_dma_refcount) != mystique->blitter_complete_refcount) ||
+ !FIFO_EMPTY)
+ ret |= (STATUS_DWGENGSTS >> 16);
+/* thread_lock_mutex(mystique->dma.lock);
+ if (mystique->dma.state == DMA_STATE_IDLE)
+ ret |= (STATUS_ENDPRDMASTS >> 16);
+ thread_unlock_mutex(mystique->dma.lock);*/
+/* pclog("Read status %02x %i %i %i fifo=%i\n", ret, mystique->busy,
+ ((mystique->blitter_submit_refcount + mystique->blitter_submit_dma_refcount) != mystique->blitter_complete_refcount),
+ !FIFO_EMPTY, FIFO_ENTRIES);*/
+// ret |= 2;
+ break;
+ case REG_STATUS+3:
+ ret = (mystique->status >> 24) & 0xff;
+ break;
+
+ case REG_IEN:
+ ret = mystique->ien & 0x64;
+ break;
+ case REG_IEN+1: case REG_IEN+2: case REG_IEN+3:
+ ret = 0;
+ break;
+
+ case REG_OPMODE:
+ ret = mystique->dmamod << 2;
+ break;
+ case REG_OPMODE+1:
+ ret = mystique->dmadatasiz;
+ break;
+ case REG_OPMODE+2:
+ ret = mystique->dirdatasiz;
+ break;
+ case REG_OPMODE+3:
+ break;
+
+ case REG_PRIMADDRESS: case REG_PRIMADDRESS+1: case REG_PRIMADDRESS+2: case REG_PRIMADDRESS+3:
+ READ8(addr, mystique->dma.primaddress);
+ break;
+ case REG_PRIMEND: case REG_PRIMEND+1: case REG_PRIMEND+2: case REG_PRIMEND+3:
+ READ8(addr, mystique->dma.primend);
+ break;
+
+ case REG_SECADDRESS: case REG_SECADDRESS+1: case REG_SECADDRESS+2: case REG_SECADDRESS+3:
+ READ8(addr, mystique->dma.secaddress);
+ break;
+
+ case REG_VCOUNT: case REG_VCOUNT+1: case REG_VCOUNT+2: case REG_VCOUNT+3:
+ READ8(addr, svga->vc);
+ break;
+
+ case REG_ATTR_IDX:
+ ret = svga_in(0x3c0, svga);
+ break;
+ case REG_ATTR_DATA:
+ ret = svga_in(0x3c1, svga);
+ break;
+
+ case REG_INSTS0:
+ ret = svga_in(0x3c2, svga);
+ break;
+
+ case REG_SEQ_IDX:
+ ret = svga_in(0x3c4, svga);
+ break;
+ case REG_SEQ_DATA:
+ ret = svga_in(0x3c5, svga);
+ break;
+
+ case REG_MISCREAD:
+ ret = svga_in(0x3cc, svga);
+ break;
+
+ case REG_GCTL_IDX:
+ ret = mystique_in(0x3ce, mystique);
+ break;
+ case REG_GCTL_DATA:
+ ret = mystique_in(0x3cf, mystique);
+ break;
+
+ case REG_CRTC_IDX:
+ ret = mystique_in(0x3d4, mystique);
+ break;
+ case REG_CRTC_DATA:
+ ret = mystique_in(0x3d5, mystique);
+ break;
+
+ case REG_INSTS1:
+ ret = mystique_in(0x3da, mystique);
+ break;
+
+ case REG_CRTCEXT_IDX:
+ ret = mystique_in(0x3de, mystique);
+ break;
+ case REG_CRTCEXT_DATA:
+ ret = mystique_in(0x3df, mystique);
+ break;
+
+ case REG_PALWTADD:
+ ret = svga_in(0x3c8, svga);
+ break;
+ case REG_PALDATA:
+ ret = svga_in(0x3c9, svga);
+ break;
+ case REG_PIXRDMSK:
+ ret = svga_in(0x3c6, svga);
+ break;
+ case REG_PALRDADD:
+ ret = svga_in(0x3c7, svga);
+ break;
+
+ case REG_X_DATAREG:
+ ret = mystique_read_xreg(mystique, mystique->xreg_idx);
+ break;
+
+ case 0x1e50: case 0x1e51: case 0x1e52: case 0x1e53:
+ case REG_ICLEAR: case REG_ICLEAR+1: case REG_ICLEAR+2: case REG_ICLEAR+3:
+ case 0x2c30: case 0x2c31: case 0x2c32: case 0x2c33:
+ case 0x3e08:
+ break;
+
+ case 0x3c08: case 0x3c09: case 0x3c0b:
+ break;
+
+ default:
+ if ((addr & 0x3fff) >= 0x2c00 && (addr & 0x3fff) < 0x2c40)
+ break;
+ if ((addr & 0x3fff) >= 0x3e00)
+ break;
+ fatal("Read MGA control %08x\n", addr & 0x3fff);
+ }
+
+// pclog("mcrb: addr=%08x ret=%02x\n", addr, ret);
+ return ret;
+}
+
+static void mystique_accel_ctrl_write_b(uint32_t addr, uint8_t val, void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+ int start_blit = 0;
+ int x;
+
+// pclog("mystique accel addr=%04x val=%02x\n", addr & 0x3fff, val);
+
+ if ((addr & 0x300) == 0x100)
+ {
+ addr &= ~0x100;
+ start_blit = 1;
+ }
+
+ switch (addr & 0x3fff)
+ {
+ case REG_MACCESS: case REG_MACCESS+1: case REG_MACCESS+2: case REG_MACCESS+3:
+ WRITE8(addr, mystique->maccess, val);
+ mystique->dwgreg.dither = mystique->maccess >> 30;
+ break;
+
+ case REG_MCTLWTST: case REG_MCTLWTST+1: case REG_MCTLWTST+2: case REG_MCTLWTST+3:
+ WRITE8(addr, mystique->mctlwtst, val);
+ break;
+
+
+ case REG_PAT0: case REG_PAT0+1: case REG_PAT0+2: case REG_PAT0+3:
+ case REG_PAT1: case REG_PAT1+1: case REG_PAT1+2: case REG_PAT1+3:
+ for (x = 0; x < 8; x++)
+ mystique->dwgreg.pattern[addr & 7][x] = val & (1 << (7-x));
+ break;
+
+ case REG_XYSTRT: case REG_XYSTRT+1:
+ WRITE8(addr&1, mystique->dwgreg.ar[5], val);
+ if (mystique->dwgreg.ar[5] & 0x8000)
+ mystique->dwgreg.ar[5] |= 0xffff8000;
+ else
+ mystique->dwgreg.ar[5] &= ~0xffff8000;
+ WRITE8(addr&1, mystique->dwgreg.xdst, val);
+ break;
+ case REG_XYSTRT+2: case REG_XYSTRT+3:
+ WRITE8(addr & 1, mystique->dwgreg.ar[6], val);
+ if (mystique->dwgreg.ar[6] & 0x8000)
+ mystique->dwgreg.ar[6] |= 0xffff8000;
+ else
+ mystique->dwgreg.ar[6] &= ~0xffff8000;
+ WRITE8(addr & 1, mystique->dwgreg.ydst, val);
+ mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg;
+ break;
+
+ case REG_XYEND: case REG_XYEND+1:
+ WRITE8(addr&1, mystique->dwgreg.ar[0], val);
+ if (mystique->dwgreg.ar[0] & 0x8000)
+ mystique->dwgreg.ar[0] |= 0xffff8000;
+ else
+ mystique->dwgreg.ar[0] &= ~0xffff8000;
+// pclog("XYEND AR[0]=%08x\n", mystique->dwgreg.ar[0]);
+ break;
+ case REG_XYEND+2: case REG_XYEND+3:
+ WRITE8(addr & 1, mystique->dwgreg.ar[2], val);
+ if (mystique->dwgreg.ar[2] & 0x8000)
+ mystique->dwgreg.ar[2] |= 0xffff8000;
+ else
+ mystique->dwgreg.ar[2] &= ~0xffff8000;
+ break;
+
+
+ case REG_SGN:
+ mystique->dwgreg.sgn.sdydxl = val & SGN_SDYDXL;
+ mystique->dwgreg.sgn.scanleft = val & SGN_SCANLEFT;
+ mystique->dwgreg.sgn.sdxl = val & SGN_SDXL;
+ mystique->dwgreg.sgn.sdy = val & SGN_SDY;
+ mystique->dwgreg.sgn.sdxr = val & SGN_SDXR;
+ break;
+ case REG_SGN+1: case REG_SGN+2: case REG_SGN+3:
+ break;
+
+
+ case REG_LEN: case REG_LEN+1:
+ WRITE8(addr, mystique->dwgreg.length, val);
+ break;
+ case REG_LEN+2:
+ break;
+ case REG_LEN+3:
+ mystique->dwgreg.beta = val >> 4;
+ if (!mystique->dwgreg.beta)
+ mystique->dwgreg.beta = 16;
+ break;
+
+ case REG_CXBNDRY: case REG_CXBNDRY+1:
+ WRITE8(addr, mystique->dwgreg.cxleft, val);
+ break;
+ case REG_CXBNDRY+2: case REG_CXBNDRY+3:
+ WRITE8(addr & 1, mystique->dwgreg.cxright, val);
+ break;
+ case REG_FXBNDRY: case REG_FXBNDRY+1:
+ WRITE8(addr, mystique->dwgreg.fxleft, val);
+ break;
+ case REG_FXBNDRY+2: case REG_FXBNDRY+3:
+ WRITE8(addr & 1, mystique->dwgreg.fxright, val);
+ break;
+
+ case REG_YDSTLEN: case REG_YDSTLEN+1:
+ WRITE8(addr, mystique->dwgreg.length, val);
+// pclog("Write YDSTLEN+%i %i\n", addr&1, mystique->dwgreg.length);
+ break;
+ case REG_YDSTLEN+2:
+ mystique->dwgreg.ydst = (mystique->dwgreg.ydst & ~0xff) | val;
+ if (mystique->dwgreg.pitch & PITCH_YLIN)
+ mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg;
+ else
+ {
+ mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg;
+ mystique->dwgreg.selline = val & 7;
+ }
+// pclog("Write YDSTLEN+2 %i %08x\n", mystique->dwgreg.ydst, mystique->dwgreg.ydst_lin);
+ break;
+ case REG_YDSTLEN+3:
+ mystique->dwgreg.ydst = (mystique->dwgreg.ydst & 0xff) | (((int32_t)(int8_t)val) << 8);
+ if (mystique->dwgreg.pitch & PITCH_YLIN)
+ mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg;
+ else
+ mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg;
+// pclog("Write YDSTLEN+3 %i %08x\n", mystique->dwgreg.ydst, mystique->dwgreg.ydst_lin);
+ break;
+
+
+ case REG_XDST: case REG_XDST+1:
+ WRITE8(addr & 1, mystique->dwgreg.xdst, val);
+ break;
+ case REG_XDST+2: case REG_XDST+3:
+ break;
+
+
+ case REG_YDSTORG: case REG_YDSTORG+1: case REG_YDSTORG+2: case REG_YDSTORG+3:
+ WRITE8(addr, mystique->dwgreg.ydstorg, val);
+ mystique->dwgreg.z_base = mystique->dwgreg.ydstorg*2 + mystique->dwgreg.zorg;
+// pclog("ydstorg=%06x z_base=%06x\n", mystique->dwgreg.ydstorg, mystique->dwgreg.z_base);
+ break;
+ case REG_YTOP: case REG_YTOP+1: case REG_YTOP+2: case REG_YTOP+3:
+ WRITE8(addr, mystique->dwgreg.ytop, val);
+ break;
+ case REG_YBOT: case REG_YBOT+1: case REG_YBOT+2: case REG_YBOT+3:
+ WRITE8(addr, mystique->dwgreg.ybot, val);
+ break;
+
+ case REG_CXLEFT: case REG_CXLEFT+1:
+ WRITE8(addr, mystique->dwgreg.cxleft, val);
+ break;
+ case REG_CXLEFT+2: case REG_CXLEFT+3:
+ break;
+ case REG_CXRIGHT: case REG_CXRIGHT+1:
+ WRITE8(addr, mystique->dwgreg.cxright, val);
+ break;
+ case REG_CXRIGHT+2: case REG_CXRIGHT+3:
+ break;
+
+ case REG_FXLEFT: case REG_FXLEFT+1:
+ WRITE8(addr, mystique->dwgreg.fxleft, val);
+ break;
+ case REG_FXLEFT+2: case REG_FXLEFT+3:
+ break;
+ case REG_FXRIGHT: case REG_FXRIGHT+1:
+ WRITE8(addr, mystique->dwgreg.fxright, val);
+ break;
+ case REG_FXRIGHT+2: case REG_FXRIGHT+3:
+ break;
+
+
+ case REG_SECADDRESS: case REG_SECADDRESS+1: case REG_SECADDRESS+2: case REG_SECADDRESS+3:
+ WRITE8(addr, mystique->dma.secaddress, val);
+ mystique->dma.sec_state = 0;
+ break;
+
+
+ case REG_TMR0: case REG_TMR0+1: case REG_TMR0+2: case REG_TMR0+3:
+ WRITE8(addr, mystique->dwgreg.tmr[0], val);
+ break;
+ case REG_TMR1: case REG_TMR1+1: case REG_TMR1+2: case REG_TMR1+3:
+ WRITE8(addr, mystique->dwgreg.tmr[1], val);
+ break;
+ case REG_TMR2: case REG_TMR2+1: case REG_TMR2+2: case REG_TMR2+3:
+ WRITE8(addr, mystique->dwgreg.tmr[2], val);
+ break;
+ case REG_TMR3: case REG_TMR3+1: case REG_TMR3+2: case REG_TMR3+3:
+ WRITE8(addr, mystique->dwgreg.tmr[3], val);
+ break;
+ case REG_TMR4: case REG_TMR4+1: case REG_TMR4+2: case REG_TMR4+3:
+ WRITE8(addr, mystique->dwgreg.tmr[4], val);
+ break;
+ case REG_TMR5: case REG_TMR5+1: case REG_TMR5+2: case REG_TMR5+3:
+ WRITE8(addr, mystique->dwgreg.tmr[5], val);
+ break;
+ case REG_TMR6: case REG_TMR6+1: case REG_TMR6+2: case REG_TMR6+3:
+ WRITE8(addr, mystique->dwgreg.tmr[6], val);
+ break;
+ case REG_TMR7: case REG_TMR7+1: case REG_TMR7+2: case REG_TMR7+3:
+ WRITE8(addr, mystique->dwgreg.tmr[7], val);
+ break;
+ case REG_TMR8: case REG_TMR8+1: case REG_TMR8+2: case REG_TMR8+3:
+ WRITE8(addr, mystique->dwgreg.tmr[8], val);
+ break;
+
+ case REG_TEXORG: case REG_TEXORG+1: case REG_TEXORG+2: case REG_TEXORG+3:
+ WRITE8(addr, mystique->dwgreg.texorg, val);
+// if ((addr & 3) == 3) pclog("texorg=%08x\n", mystique->dwgreg.texorg);
+ break;
+ case REG_TEXWIDTH: case REG_TEXWIDTH+1: case REG_TEXWIDTH+2: case REG_TEXWIDTH+3:
+ WRITE8(addr, mystique->dwgreg.texwidth, val);
+// if ((addr & 3) == 3) pclog("texwith=%08x\n", mystique->dwgreg.texwidth);
+ break;
+ case REG_TEXHEIGHT: case REG_TEXHEIGHT+1: case REG_TEXHEIGHT+2: case REG_TEXHEIGHT+3:
+ WRITE8(addr, mystique->dwgreg.texheight, val);
+// if ((addr & 3) == 3) pclog("texheight=%08x %i %i\n", mystique->dwgreg.texheight, mystique->dwgreg.texheight&0x3f, (int)(((mystique->dwgreg.texheight >> 9) & 0x3f) | ((mystique->dwgreg.texheight & (1 << 14)) ? 0xffffffc0 : 0)));
+ break;
+ case REG_TEXCTL: case REG_TEXCTL+1: case REG_TEXCTL+2: case REG_TEXCTL+3:
+ WRITE8(addr, mystique->dwgreg.texctl, val);
+// if ((addr & 3) == 3) pclog("texctl=%08x\n", mystique->dwgreg.texctl);
+ mystique->dwgreg.ta_key = (mystique->dwgreg.texctl & TEXCTL_TAKEY) ? 1 : 0;
+ mystique->dwgreg.ta_mask = (mystique->dwgreg.texctl & TEXCTL_TAMASK) ? 1 : 0;
+ break;
+ case REG_TEXTRANS: case REG_TEXTRANS+1: case REG_TEXTRANS+2: case REG_TEXTRANS+3:
+ WRITE8(addr, mystique->dwgreg.textrans, val);
+// /*if ((addr & 3) == 3) */pclog("textrans=%08x\n", mystique->dwgreg.textrans);
+ break;
+
+ case 0x1c28: case 0x1c29: case 0x1c2a: case 0x1c2b:
+ case 0x1c2c: case 0x1c2d: case 0x1c2e: case 0x1c2f:
+ case 0x1cc4: case 0x1cc5: case 0x1cc6: case 0x1cc7:
+ case 0x1cd4: case 0x1cd5: case 0x1cd6: case 0x1cd7:
+ case 0x1ce4: case 0x1ce5: case 0x1ce6: case 0x1ce7:
+ case 0x1cf4: case 0x1cf5: case 0x1cf6: case 0x1cf7:
+ break;
+
+ case REG_OPMODE:
+ mystique->dwgreg.dmamod = (val >> 2) & 3;
+ mystique->dma.iload_state = 0;
+ break;
+
+ default:
+ if ((addr & 0x3fff) >= 0x2c4c && (addr & 0x3fff) <= 0x2cff)
+ break;
+ fatal("Write MGA accel control %08x %02x\n", addr & 0x3fff, val);
+ break;
+ }
+
+ if (start_blit)
+ {
+ mystique_start_blit(mystique);
+// fatal("Start blit\n");
+ }
+}
+static void mystique_ctrl_write_b(uint32_t addr, uint8_t val, void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+ svga_t *svga = &mystique->svga;
+
+// pclog("mystique addr=%04x val=%02x\n", addr & 0x3fff, val);
+
+ if ((addr & 0x3fff) < 0x1c00)
+ {
+ mystique_iload_write_b(addr, val, p);
+ return;
+ }
+ if ((addr & 0x3e00) == 0x1c00 || (addr & 0x3e00) == 0x2c00)
+ {
+ if ((addr & 0x300) == 0x100)
+ mystique->blitter_submit_refcount++;
+// pclog("mystique queue addr=%04x val=%02x\n", addr & 0x3fff, val);
+ mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_BYTE);
+ return;
+ }
+
+ switch (addr & 0x3fff)
+ {
+ case REG_ICLEAR:
+// pclog("ICLEAR %02x\n", val);
+ if (val & ICLEAR_SOFTRAPICLR)
+ {
+ mystique->status &= ~STATUS_SOFTRAPEN;
+ mystique_update_irqs(mystique);
+ }
+ if (val & ICLEAR_VLINEICLR)
+ {
+ mystique->status &= ~STATUS_VLINEPEN;
+ mystique_update_irqs(mystique);
+ }
+ break;
+ case REG_ICLEAR+1: case REG_ICLEAR+2: case REG_ICLEAR+3:
+ break;
+
+ case REG_IEN:
+ mystique->ien = val & 0x65;
+// pclog("Write IEN %02x\n", val);
+ break;
+ case REG_IEN+1: case REG_IEN+2: case REG_IEN+3:
+ break;
+
+ case REG_OPMODE:
+ mystique->dmamod = (val >> 2) & 3;
+// pclog("OPMODE\n");
+ mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_BYTE);
+ break;
+ case REG_OPMODE+1:
+ mystique->dmadatasiz = val & 3;
+ break;
+ case REG_OPMODE+2:
+ mystique->dirdatasiz = val & 3;
+ break;
+ case REG_OPMODE+3:
+ break;
+
+ case REG_PRIMADDRESS: case REG_PRIMADDRESS+1: case REG_PRIMADDRESS+2: case REG_PRIMADDRESS+3:
+ thread_lock_mutex(mystique->dma.lock);
+ WRITE8(addr, mystique->dma.primaddress, val);
+ mystique->dma.pri_state = 0;
+// pclog("PRIMADDRESS write %04x %08x\n", addr, mystique->dma.primaddress);
+ thread_unlock_mutex(mystique->dma.lock);
+ break;
+
+ case REG_DMAMAP: case REG_DMAMAP+0x1: case REG_DMAMAP+0x2: case REG_DMAMAP+0x3:
+ case REG_DMAMAP+0x4: case REG_DMAMAP+0x5: case REG_DMAMAP+0x6: case REG_DMAMAP+0x7:
+ case REG_DMAMAP+0x8: case REG_DMAMAP+0x9: case REG_DMAMAP+0xa: case REG_DMAMAP+0xb:
+ case REG_DMAMAP+0xc: case REG_DMAMAP+0xd: case REG_DMAMAP+0xe: case REG_DMAMAP+0xf:
+ mystique->dmamap[addr & 0xf] = val;
+ break;
+
+ case REG_RST: case REG_RST+1: case REG_RST+2: case REG_RST+3:
+// pclog("Write REG_RST\n");
+ wait_fifo_idle(mystique);
+ mystique->busy = 0;
+ mystique->blitter_submit_refcount = 0;
+ mystique->blitter_submit_dma_refcount = 0;
+ mystique->blitter_complete_refcount = 0;
+ mystique->dwgreg.iload_rem_count = 0;
+ mystique->status = STATUS_ENDPRDMASTS;
+ break;
+
+ case REG_ATTR_IDX:
+ svga_out(0x3c0, val, svga);
+ break;
+ case REG_ATTR_DATA:
+ svga_out(0x3c1, val, svga);
+ break;
+
+ case REG_MISC:
+ svga_out(0x3c2, val, svga);
+ break;
+
+ case REG_SEQ_IDX:
+ svga_out(0x3c4, val, svga);
+ break;
+ case REG_SEQ_DATA:
+ svga_out(0x3c5, val, svga);
+ break;
+
+ case REG_GCTL_IDX:
+ mystique_out(0x3ce, val, mystique);
+ break;
+ case REG_GCTL_DATA:
+ mystique_out(0x3cf, val, mystique);
+ break;
+
+ case REG_CRTC_IDX:
+ mystique_out(0x3d4, val, mystique);
+ break;
+ case REG_CRTC_DATA:
+ mystique_out(0x3d5, val, mystique);
+ break;
+
+ case REG_CRTCEXT_IDX:
+ mystique_out(0x3de, val, mystique);
+ break;
+ case REG_CRTCEXT_DATA:
+ mystique_out(0x3df, val, mystique);
+ break;
+
+ case REG_CACHEFLUSH:
+ break;
+
+ case REG_PALWTADD:
+ svga_out(0x3c8, val, svga);
+ mystique->xreg_idx = val;
+ break;
+ case REG_PALDATA:
+ svga_out(0x3c9, val, svga);
+ break;
+ case REG_PIXRDMSK:
+ svga_out(0x3c6, val, svga);
+ break;
+ case REG_PALRDADD:
+ svga_out(0x3c7, val, svga);
+ break;
+
+ case REG_X_DATAREG:
+ mystique_write_xreg(mystique, mystique->xreg_idx, val);
+ break;
+
+ case REG_CURPOSX: case REG_CURPOSX+1:
+ WRITE8(addr, mystique->cursor.pos_x, val);
+ svga->hwcursor.x = mystique->cursor.pos_x - 64;
+ break;
+ case REG_CURPOSY: case REG_CURPOSY+1:
+ WRITE8(addr & 1, mystique->cursor.pos_y, val);
+ svga->hwcursor.y = mystique->cursor.pos_y - 64;
+ break;
+
+ case 0x1e50: case 0x1e51: case 0x1e52: case 0x1e53:
+ case 0x3c0b: case 0x3e02: case 0x3e08:
+ break;
+
+ default:
+ if ((addr & 0x3fff) >= 0x2c4c && (addr & 0x3fff) <= 0x2cff)
+ break;
+ if ((addr & 0x3fff) >= 0x3e00)
+ break;
+ fatal("Write MGA control %08x %02x\n", addr & 0x3fff, val);
+ break;
+ }
+}
+
+static uint32_t mystique_ctrl_read_l(uint32_t addr, void *p)
+{
+ uint32_t ret;
+
+// pclog("mystique_ctrl_read_l: addr=%08x %08x\n", addr, cpu_state.pc);
+ if ((addr & 0x3fff) < 0x1c00)
+ return mystique_iload_read_l(addr, p);
+
+ ret = mystique_ctrl_read_b(addr, p);
+ ret |= mystique_ctrl_read_b(addr+1, p) << 8;
+ ret |= mystique_ctrl_read_b(addr+2, p) << 16;
+ ret |= mystique_ctrl_read_b(addr+3, p) << 24;
+// pclog("mcrl: addr=%08x ret=%08x %08x\n", addr, ret, mystique->status);
+
+ return ret;
+}
+
+static void mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+ int start_blit = 0;
+
+// pclog("mystique accel addr=%04x val=%08x\n", addr & 0x3fff, val);
+ if ((addr & 0x300) == 0x100)
+ {
+ addr &= ~0x100;
+ start_blit = 1;
+ }
+
+ switch (addr & 0x3ffc)
+ {
+ case REG_DWGCTL:
+// pclog(" dwgctrl write %08x %08x\n", addr2, val);
+ mystique->dwgreg.dwgctrl = val;
+ break;
+
+ case REG_ZORG:
+ mystique->dwgreg.zorg = val;
+ mystique->dwgreg.z_base = mystique->dwgreg.ydstorg*2 + mystique->dwgreg.zorg;
+// pclog("zorg=%08x z_base=%08x\n", mystique->dwgreg.zorg, mystique->dwgreg.z_base);
+ break;
+
+ case REG_PLNWT:
+ mystique->dwgreg.plnwt = val;
+ break;
+
+ case REG_SHIFT:
+ mystique->dwgreg.funcnt = val & 0xff;
+ mystique->dwgreg.xoff = val & 7;
+ mystique->dwgreg.yoff = (val >> 4) & 7;
+ mystique->dwgreg.stylelen = (val >> 16) & 0xff;
+ break;
+
+ case REG_PITCH:
+ mystique->dwgreg.pitch = val & 0xffff;
+ if (mystique->dwgreg.pitch & PITCH_YLIN)
+ mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg;
+ else
+ mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg;
+// pclog("pitch=%04x %i\n", mystique->dwgreg.pitch, addr&1);
+ break;
+
+ case REG_YDST:
+ mystique->dwgreg.ydst = val & 0x3fffff;
+ if (mystique->dwgreg.pitch & PITCH_YLIN)
+ {
+ mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg;
+ mystique->dwgreg.selline = val >> 29;
+ }
+ else
+ {
+ mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg;
+ mystique->dwgreg.selline = val & 7;
+ }
+// pclog("ydst=%i ydsth=%08x %08x pitch=%08x\n", mystique->dwgreg.ydst, mystique->dwgreg.ydst, mystique->dwgreg.ydst_lin, mystique->dwgreg.pitch);
+ break;
+
+ case REG_BCOL:
+ mystique->dwgreg.bcol = val;
+// pclog("BCOL %i %02x\n", addr & 3, val);
+ break;
+ case REG_FCOL:
+ mystique->dwgreg.fcol = val;
+// pclog("FCOL %i %02x\n", addr & 3, val);
+ break;
+
+ case REG_SRC0:
+ mystique->dwgreg.src[0] = val;
+ if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD)
+ blit_iload_write(mystique, mystique->dwgreg.src[0], 32);
+ break;
+ case REG_SRC1:
+ mystique->dwgreg.src[1] = val;
+ if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD)
+ blit_iload_write(mystique, mystique->dwgreg.src[1], 32);
+ break;
+ case REG_SRC2:
+ mystique->dwgreg.src[2] = val;
+ if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD)
+ blit_iload_write(mystique, mystique->dwgreg.src[2], 32);
+ break;
+ case REG_SRC3:
+ mystique->dwgreg.src[3] = val;
+ if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD)
+ blit_iload_write(mystique, mystique->dwgreg.src[3], 32);
+ break;
+
+
+ case REG_DMAPAD:
+ if (mystique->busy && (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD)
+ blit_iload_write(mystique, val, 32);
+ break;
+
+ case REG_AR0:
+ mystique->dwgreg.ar[0] = val;
+// pclog("AR[0]=%08x\n", mystique->dwgreg.ar[0]);
+ break;
+ case REG_AR1:
+ mystique->dwgreg.ar[1] = val;
+ break;
+ case REG_AR2:
+ mystique->dwgreg.ar[2] = val;
+ break;
+ case REG_AR3:
+ mystique->dwgreg.ar[3] = val;
+// pclog("AR[3]=%08x\n", mystique->dwgreg.ar[3]);
+ break;
+ case REG_AR4:
+ mystique->dwgreg.ar[4] = val;
+ break;
+ case REG_AR5:
+ mystique->dwgreg.ar[5] = val;
+ break;
+ case REG_AR6:
+ mystique->dwgreg.ar[6] = val;
+ break;
+
+ case REG_DR0:
+ mystique->dwgreg.dr[0] = val;
+ break;
+ case REG_DR2:
+ mystique->dwgreg.dr[2] = val;
+ break;
+ case REG_DR3:
+ mystique->dwgreg.dr[3] = val;
+ break;
+ case REG_DR4:
+ mystique->dwgreg.dr[4] = val;
+// if ((addr & 3) == 3) pclog("DR[4]=%08x\n", mystique->dwgreg.dr[4]);
+ break;
+ case REG_DR6:
+ mystique->dwgreg.dr[6] = val;
+// if ((addr & 3) == 3) pclog("DR[6]=%08x\n", mystique->dwgreg.dr[6]);
+ break;
+ case REG_DR7:
+ mystique->dwgreg.dr[7] = val;
+// if ((addr & 3) == 3) pclog("DR[7]=%08x\n", mystique->dwgreg.dr[7]);
+ break;
+ case REG_DR8:
+ mystique->dwgreg.dr[8] = val;
+ break;
+ case REG_DR10:
+ mystique->dwgreg.dr[10] = val;
+ break;
+ case REG_DR11:
+ mystique->dwgreg.dr[11] = val;
+ break;
+ case REG_DR12:
+ mystique->dwgreg.dr[12] = val;
+ break;
+ case REG_DR14:
+ mystique->dwgreg.dr[14] = val;
+ break;
+ case REG_DR15:
+ mystique->dwgreg.dr[15] = val;
+ break;
+
+ case REG_SECEND:
+// pclog("SECEND write %08x\n", val);
+ mystique->dma.secend = val;
+ if (mystique->dma.state != DMA_STATE_SEC && (mystique->dma.secaddress & DMA_ADDR_MASK) != (mystique->dma.secend & DMA_ADDR_MASK))
+ {
+// pclog(" DMA state STATE_SEC\n");
+ mystique->dma.state = DMA_STATE_SEC;
+ }
+ break;
+
+ case REG_SOFTRAP:
+// pclog("SOFTRAP\n");
+/* mystique->dma.secaddress = val;*/
+ mystique->dma.state = DMA_STATE_IDLE;
+ mystique->endprdmasts_pending = 1;
+ mystique->softrap_pending_val = val;
+ mystique->softrap_pending = 1;
+// pclog("SOFTRAP DMA state STATE_IDLE\n");
+/* mystique->status |= STATUS_SOFTRAPEN;
+ mystique_update_irqs(mystique);*/
+ break;
+
+ default:
+ mystique_accel_ctrl_write_b(addr, val & 0xff, p);
+ mystique_accel_ctrl_write_b(addr+1, (val >> 8) & 0xff, p);
+ mystique_accel_ctrl_write_b(addr+2, (val >> 16) & 0xff, p);
+ mystique_accel_ctrl_write_b(addr+3, (val >> 24) & 0xff, p);
+ break;
+ }
+
+ if (start_blit)
+ {
+ mystique_start_blit(mystique);
+// fatal("Start blit\n");
+ }
+}
+
+static void mystique_ctrl_write_l(uint32_t addr, uint32_t val, void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+ uint32_t reg_addr;
+
+// pclog("mystique addr=%04x val=%08x\n", addr & 0x3fff, val);
+ if ((addr & 0x3fff) < 0x1c00)
+ {
+ mystique_iload_write_l(addr, val, p);
+ return;
+ }
+
+ if ((addr & 0x3e00) == 0x1c00 || (addr & 0x3e00) == 0x2c00)
+ {
+ if ((addr & 0x300) == 0x100)
+ mystique->blitter_submit_refcount++;
+// pclog("mystique queue addr=%04x val=%08x\n", addr & 0x3fff, val);
+ mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_LONG);
+ return;
+ }
+
+ switch (addr & 0x3ffc)
+ {
+ case REG_PRIMEND:
+ thread_lock_mutex(mystique->dma.lock);
+// pclog("PRIMEND write %08x\n", val);
+ mystique->dma.primend = val;
+ if (mystique->dma.state == DMA_STATE_IDLE && (mystique->dma.primaddress & DMA_ADDR_MASK) != (mystique->dma.primend & DMA_ADDR_MASK))
+ {
+// pclog("Clear DMA end flag\n");
+ mystique->endprdmasts_pending = 0;
+ mystique->status &= ~STATUS_ENDPRDMASTS;
+
+ mystique->dma.state = DMA_STATE_PRI;
+// pclog(" DMA state STATE_PRI\n");
+ mystique->dma.pri_state = 0;
+ wake_fifo_thread(mystique);
+ }
+ thread_unlock_mutex(mystique->dma.lock);
+ break;
+
+ case REG_DWG_INDIR_WT: case REG_DWG_INDIR_WT+0x04: case REG_DWG_INDIR_WT+0x08: case REG_DWG_INDIR_WT+0x0c:
+ case REG_DWG_INDIR_WT+0x10: case REG_DWG_INDIR_WT+0x14: case REG_DWG_INDIR_WT+0x18: case REG_DWG_INDIR_WT+0x1c:
+ case REG_DWG_INDIR_WT+0x20: case REG_DWG_INDIR_WT+0x24: case REG_DWG_INDIR_WT+0x28: case REG_DWG_INDIR_WT+0x2c:
+ case REG_DWG_INDIR_WT+0x30: case REG_DWG_INDIR_WT+0x34: case REG_DWG_INDIR_WT+0x38: case REG_DWG_INDIR_WT+0x3c:
+ reg_addr = (mystique->dmamap[(addr >> 2) & 0xf] & 0x7f) << 2;
+ if (mystique->dmamap[(addr >> 2) & 0xf] & 0x80)
+ reg_addr += 0x2c00;
+ else
+ reg_addr += 0x1c00;
+
+ if ((reg_addr & 0x300) == 0x100)
+ mystique->blitter_submit_refcount++;
+
+// pclog("mystique queue dwg addr=%04x val=%08x\n", reg_addr, val);
+ mystique_queue(mystique, reg_addr, val, FIFO_WRITE_CTRL_LONG);
+ break;
+
+ default:
+ mystique_ctrl_write_b(addr, val & 0xff, p);
+ mystique_ctrl_write_b(addr+1, (val >> 8) & 0xff, p);
+ mystique_ctrl_write_b(addr+2, (val >> 16) & 0xff, p);
+ mystique_ctrl_write_b(addr+3, (val >> 24) & 0xff, p);
+ break;
+ }
+}
+
+static uint8_t mystique_iload_read_b(uint32_t addr, void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+
+ wait_fifo_idle(mystique);
+ if (!mystique->busy)
+ {
+// fatal("mystique_iload_read_b: %08x !busy\n", addr);
+ return 0xff;
+ }
+
+// pclog("Readb MGA ILOAD %08x\n", addr);
+ return blit_idump_read(mystique);
+}
+static uint32_t mystique_iload_read_l(uint32_t addr, void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+
+ wait_fifo_idle(mystique);
+ if (!mystique->busy)
+ {
+// fatal("mystique_iload_read_l: !busy\n");
+ return 0xffffffff;
+ }
+
+// pclog("Readl MGA ILOAD %08x %i\n", addr, mystique->dwgreg.words);
+ mystique->dwgreg.words++;
+ return blit_idump_read(mystique);
+}
+static void mystique_iload_write_b(uint32_t addr, uint8_t val, void *p)
+{
+ fatal("Write MGA ILOAD %08x %02x\n", addr, val);
+}
+static void mystique_iload_write_l(uint32_t addr, uint32_t val, void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+
+// pclog("mystique queue iload addr=%04x val=%08x\n", addr, val);
+ mystique_queue(mystique, 0, val, FIFO_WRITE_ILOAD_LONG);
+}
+
+static void mystique_accel_iload_write_l(uint32_t addr, uint32_t val, void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+
+// pclog(" Write ILOAD %08x %i %i %08x\n", val, mystique->dwgreg.dmamod, mystique->dma.iload_state, mystique->dwgreg.dwgctrl);
+ switch (mystique->dwgreg.dmamod)
+ {
+ case DMA_MODE_REG:
+ if (mystique->dma.iload_state == 0)
+ {
+// pclog(" ILOAD header\n");
+ mystique->dma.iload_header = val;
+ mystique->dma.iload_state = 1;
+ }
+ else
+ {
+ uint32_t reg_addr = (mystique->dma.iload_header & 0x7f) << 2;
+ if (mystique->dma.iload_header & 0x80)
+ reg_addr += 0x2c00;
+ else
+ reg_addr += 0x1c00;
+
+// pclog(" ILOAD write %08x to %02x %04x\n", val, mystique->dma.iload_header & 0xff, reg_addr);
+ if ((reg_addr & 0x300) == 0x100)
+ mystique->blitter_submit_dma_refcount++;
+ mystique_accel_ctrl_write_l(reg_addr, val, mystique);
+
+ mystique->dma.iload_header >>= 8;
+ mystique->dma.iload_state = (mystique->dma.iload_state == 4) ? 0 : (mystique->dma.iload_state+1);
+ }
+ break;
+
+ case DMA_MODE_BLIT:
+ if (mystique->busy)
+ blit_iload_write(mystique, val, 32);
+ break;
+
+ default:
+ fatal("ILOAD write DMAMOD %i\n", mystique->dwgreg.dmamod);
+ }
+}
+
+
+static uint8_t mystique_readb_linear(uint32_t addr, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+
+ egareads++;
+
+ cycles -= video_timing_read_b;
+ cycles_lost += video_timing_read_b;
+
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return 0xff;
+
+ return svga->vram[addr & svga->vram_mask];
+}
+static uint16_t mystique_readw_linear(uint32_t addr, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+
+ egareads += 2;
+
+ cycles -= video_timing_read_w;
+ cycles_lost += video_timing_read_w;
+
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return 0xffff;
+
+ return *(uint16_t *)&svga->vram[addr & svga->vram_mask];
+}
+static uint32_t mystique_readl_linear(uint32_t addr, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+
+ egareads += 4;
+
+ cycles -= video_timing_read_l;
+ cycles_lost += video_timing_read_l;
+
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return 0xffffffff;
+
+ return *(uint32_t *)&svga->vram[addr & svga->vram_mask];
+}
+
+static void mystique_writeb_linear(uint32_t addr, uint8_t val, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+
+ egawrites++;
+
+ 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;
+ svga->changedvram[addr >> 12] = changeframecount;
+ svga->vram[addr] = val;
+}
+static void mystique_writew_linear(uint32_t addr, uint16_t val, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+
+ egawrites += 2;
+
+ 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;
+ svga->changedvram[addr >> 12] = changeframecount;
+ *(uint16_t *)&svga->vram[addr] = val;
+}
+static void mystique_writel_linear(uint32_t addr, uint32_t val, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+
+ egawrites += 4;
+
+ cycles -= video_timing_write_l;
+ cycles_lost += video_timing_write_l;
+
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return;
+ addr &= svga->vram_mask;
+ svga->changedvram[addr >> 12] = changeframecount;
+ *(uint32_t *)&svga->vram[addr] = val;
+}
+
+
+static uint32_t mystique_dma_read(uint32_t addr)
+{
+ if ((addr & DMA_ADDR_MASK) > (mem_size * 1024))
+ {
+// pclog("PCI DMA out of range\n");
+ return -1;
+ }
+ return *(uint32_t *)&ram[addr & DMA_ADDR_MASK];
+}
+
+static void run_dma(mystique_t *mystique)
+{
+ int words_transferred = 0;
+
+ thread_lock_mutex(mystique->dma.lock);
+
+ if (mystique->dma.state == DMA_STATE_IDLE)
+ {
+ thread_unlock_mutex(mystique->dma.lock);
+ return;
+ }
+
+ while (words_transferred < DMA_MAX_WORDS && mystique->dma.state != DMA_STATE_IDLE)
+ {
+ switch (mystique->dma.state)// != DMA_STATE_IDLE)
+ {
+ case DMA_STATE_PRI:
+ switch (mystique->dma.primaddress & DMA_MODE_MASK)
+ {
+ case DMA_MODE_REG:
+ if (mystique->dma.pri_state == 0)
+ {
+ mystique->dma.pri_header = mystique_dma_read(mystique->dma.primaddress);
+// pclog("DMA pri read header %08x from %08x %08x\n", mystique->dma.pri_header, mystique->dma.primaddress, mystique->dma.primend);
+ mystique->dma.primaddress += 4;
+ }
+
+// if ((mystique->dma.pri_header & 0xff) != 0x15)
+ {
+ uint32_t val = mystique_dma_read(mystique->dma.primaddress);
+ uint32_t reg_addr;
+
+ mystique->dma.primaddress += 4;
+
+ reg_addr = (mystique->dma.pri_header & 0x7f) << 2;
+ if (mystique->dma.pri_header & 0x80)
+ reg_addr += 0x2c00;
+ else
+ reg_addr += 0x1c00;
+
+// pclog(" DMA pri write %08x to %02x %04x %08x %08x\n", val, mystique->dma.pri_header & 0xff, reg_addr, (mystique->dma.primaddress & DMA_ADDR_MASK), (mystique->dma.primend & DMA_ADDR_MASK));
+ if ((reg_addr & 0x300) == 0x100)
+ mystique->blitter_submit_dma_refcount++;
+
+ mystique_accel_ctrl_write_l(reg_addr, val, mystique);
+ }
+
+ mystique->dma.pri_header >>= 8;
+ mystique->dma.pri_state = (mystique->dma.pri_state + 1) & 3;
+
+ words_transferred++;
+ if (mystique->dma.state == DMA_STATE_SEC)
+ mystique->dma.pri_state = 0;
+ else if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK))
+ {
+// pclog("DMA pri end\n");
+ mystique->endprdmasts_pending = 1;
+ mystique->dma.state = DMA_STATE_IDLE;
+ }
+ break;
+
+ default:
+ fatal("DMA_STATE_PRI: mode %i\n", mystique->dma.primaddress & DMA_MODE_MASK);
+ }
+ break;
+
+ case DMA_STATE_SEC:
+ switch (mystique->dma.secaddress & DMA_MODE_MASK)
+ {
+ case DMA_MODE_REG:
+ if (mystique->dma.sec_state == 0)
+ {
+ mystique->dma.sec_header = mystique_dma_read(mystique->dma.secaddress);
+// pclog("DMA sec read header %08x from %08x %08x\n", mystique->dma.sec_header, mystique->dma.secaddress, mystique->dma.secend);
+ mystique->dma.secaddress += 4;
+ }
+
+// if ((mystique->dma.sec_header & 0xff) != 0x15)
+ {
+ uint32_t val = mystique_dma_read(mystique->dma.secaddress);
+ uint32_t reg_addr;
+
+ mystique->dma.secaddress += 4;
+
+ reg_addr = (mystique->dma.sec_header & 0x7f) << 2;
+ if (mystique->dma.sec_header & 0x80)
+ reg_addr += 0x2c00;
+ else
+ reg_addr += 0x1c00;
+
+// pclog(" DMA sec write %08x to %02x %04x %08x %08x\n", val, mystique->dma.sec_header & 0xff, reg_addr, (mystique->dma.secaddress & DMA_ADDR_MASK), (mystique->dma.secend & DMA_ADDR_MASK));
+ if ((reg_addr & 0x300) == 0x100)
+ mystique->blitter_submit_dma_refcount++;
+
+ mystique_accel_ctrl_write_l(reg_addr, val, mystique);
+ }
+
+ mystique->dma.sec_header >>= 8;
+ mystique->dma.sec_state = (mystique->dma.sec_state + 1) & 3;
+
+ words_transferred++;
+ if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK))
+ {
+// pclog("DMA sec end\n");
+ if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK))
+ {
+// pclog("DMA pri end\n");
+ mystique->endprdmasts_pending = 1;
+ mystique->dma.state = DMA_STATE_IDLE;
+ }
+ else
+ {
+// pclog("DMA pri resume\n");
+ mystique->dma.state = DMA_STATE_PRI;
+ }
+ }
+ break;
+
+ case DMA_MODE_BLIT:
+ {
+ uint32_t val = mystique_dma_read(mystique->dma.secaddress);
+// pclog(" DMA_MODE_BLIT %08x %08x %08x %08x\n", mystique->dma.secaddress & DMA_ADDR_MASK, mystique->dma.secend & DMA_ADDR_MASK, mystique->dwgreg.dwgctrl_running, mystique->maccess_running);
+ mystique->dma.secaddress += 4;
+
+ if (mystique->busy)
+ blit_iload_write(mystique, val, 32);
+
+ words_transferred++;
+ if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK))
+ {
+// pclog("DMA sec end\n");
+ if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK))
+ {
+// pclog("DMA pri end\n");
+ mystique->endprdmasts_pending = 1;
+ mystique->dma.state = DMA_STATE_IDLE;
+ }
+ else
+ {
+// pclog("DMA pri resume\n");
+ mystique->dma.state = DMA_STATE_PRI;
+ }
+ }
+ }
+ break;
+
+ default:
+ fatal("DMA_STATE_SEC: mode %i\n", mystique->dma.secaddress & DMA_MODE_MASK);
+ }
+ break;
+ }
+ }
+ thread_unlock_mutex(mystique->dma.lock);
+}
+
+static void fifo_thread(void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+
+ while (1)
+ {
+ thread_set_event(mystique->fifo_not_full_event);
+ thread_wait_event(mystique->wake_fifo_thread, -1);
+ thread_reset_event(mystique->wake_fifo_thread);
+
+ while (!FIFO_EMPTY || mystique->dma.state != DMA_STATE_IDLE)
+ {
+ int words_transferred = 0;
+
+ while (!FIFO_EMPTY && words_transferred < 100)
+ {
+ fifo_entry_t *fifo = &mystique->fifo[mystique->fifo_read_idx & FIFO_MASK];
+
+ switch (fifo->addr_type & FIFO_TYPE)
+ {
+ case FIFO_WRITE_CTRL_BYTE:
+ mystique_accel_ctrl_write_b(fifo->addr_type & FIFO_ADDR, fifo->val, mystique);
+ break;
+ case FIFO_WRITE_CTRL_LONG:
+ mystique_accel_ctrl_write_l(fifo->addr_type & FIFO_ADDR, fifo->val, mystique);
+ break;
+ case FIFO_WRITE_ILOAD_LONG:
+ mystique_accel_iload_write_l(fifo->addr_type & FIFO_ADDR, fifo->val, mystique);
+ break;
+ }
+
+ fifo->addr_type = FIFO_INVALID;
+ mystique->fifo_read_idx++;
+
+ if (FIFO_ENTRIES > FIFO_THRESHOLD)
+ thread_set_event(mystique->fifo_not_full_event);
+
+ words_transferred++;
+ }
+ /*Only run DMA once the FIFO is empty. Required by
+ Screamer 2 / Rally which will incorrectly clip an ILOAD
+ if DMA runs ahead*/
+ if (!words_transferred)
+ run_dma(mystique);
+ }
+ }
+}
+
+static void wake_fifo_thread(mystique_t *mystique)
+{
+ if (!timer_is_enabled(&mystique->wake_timer))
+ {
+ /*Don't wake FIFO thread immediately - if we do that it will probably
+ process one word and go back to sleep, requiring it to be woken on
+ almost every write. Instead, wait a short while so that the CPU
+ emulation writes more data so we have more batched-up work.*/
+ timer_set_delay_u64(&mystique->wake_timer, WAKE_DELAY);
+ }
+}
+
+static void wake_fifo_thread_now(mystique_t *mystique)
+{
+ thread_set_event(mystique->wake_fifo_thread);
+}
+
+static void mystique_wake_timer(void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+
+ thread_set_event(mystique->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
+}
+
+static void wait_fifo_idle(mystique_t *mystique)
+{
+ while (!FIFO_EMPTY)
+ {
+ wake_fifo_thread_now(mystique);
+ thread_wait_event(mystique->fifo_not_full_event, 1);
+ }
+}
+
+/*IRQ code (PCI & PIC) is not currently thread safe. SOFTRAP IRQ requests must
+ therefore be submitted from the main emulation thread, in this case via a timer
+ callback. End-of-DMA status is also deferred here to prevent races between
+ SOFTRAP IRQs and code reading the status register. Croc will get into an IRQ
+ loop and triple fault if the ENDPRDMASTS flag is seen before the IRQ is taken*/
+static void mystique_softrap_pending_timer(void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+
+ timer_advance_u64(&mystique->softrap_pending_timer, TIMER_USEC * 100);
+
+ if (mystique->endprdmasts_pending)
+ {
+ mystique->endprdmasts_pending = 0;
+ mystique->status |= STATUS_ENDPRDMASTS;
+ }
+ if (mystique->softrap_pending)
+ {
+ mystique->softrap_pending = 0;
+
+// pclog("Take SOFTRAP %08x\n", cpu_state.pc);
+ mystique->dma.secaddress = mystique->softrap_pending_val;
+ mystique->status |= STATUS_SOFTRAPEN;
+ mystique_update_irqs(mystique);
+ }
+}
+
+static void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type)
+{
+ fifo_entry_t *fifo = &mystique->fifo[mystique->fifo_write_idx & FIFO_MASK];
+
+ if (FIFO_FULL)
+ {
+ thread_reset_event(mystique->fifo_not_full_event);
+ if (FIFO_FULL)
+ {
+ thread_wait_event(mystique->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/
+ }
+ }
+
+ fifo->val = val;
+ fifo->addr_type = (addr & FIFO_ADDR) | type;
+
+ mystique->fifo_write_idx++;
+
+ if (FIFO_ENTRIES > FIFO_THRESHOLD || FIFO_ENTRIES < 8)
+ wake_fifo_thread(mystique);
+
+// wait_fifo_idle(mystique);
+}
+
+
+
+static uint32_t bitop(uint32_t src, uint32_t dst, uint32_t dwgctrl)
+{
+ switch (dwgctrl & DWGCTRL_BOP_MASK)
+ {
+ case BOP(0x0): return 0;
+ case BOP(0x1): return ~(dst | src);
+ case BOP(0x2): return dst & ~src;
+ case BOP(0x3): return ~src;
+ case BOP(0x4): return ~dst & src;
+ case BOP(0x5): return ~dst;
+ case BOP(0x6): return dst ^ src;
+ case BOP(0x7): return ~(dst & src);
+ case BOP(0x8): return dst & src;
+ case BOP(0x9): return ~(dst ^ src);
+ case BOP(0xa): return dst;
+ case BOP(0xb): return dst | ~src;
+ case BOP(0xc): return src;
+ case BOP(0xd): return ~dst | src;
+ case BOP(0xe): return dst | src;
+ case BOP(0xf): return ~0;
+ }
+ return 0;
+}
+
+static uint16_t dither(mystique_t *mystique, int r, int g, int b, int x, int y)
+{
+ switch (mystique->dwgreg.dither)
+ {
+ case DITHER_NONE_555:
+ return (b >> 3) | ((g >> 3) << 5) | ((r >> 3) << 10);
+
+ case DITHER_NONE_565:
+ return (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11);
+
+ case DITHER_555:
+ return dither5[b][y][x] | (dither5[g][y][x] << 5) | (dither5[r][y][x] << 10);
+
+ case DITHER_565:
+ default:
+ return dither5[b][y][x] | (dither6[g][y][x] << 5) | (dither5[r][y][x] << 11);
+ }
+}
+
+
+static uint32_t blit_idump_idump(mystique_t *mystique)
+{
+ svga_t *svga = &mystique->svga;
+ uint64_t val64 = 0;
+ uint32_t val = 0;
+ int count = 0;
+
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK)
+ {
+ case DWGCTRL_ATYPE_RPL:
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK)
+ {
+ case DWGCTRL_BLTMOD_BU32RGB:
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_8:
+// pclog(" IDUMP %08x\n", mystique->dwgreg.src_addr);
+ while (count < 32)
+ {
+ val |= (svga->vram[mystique->dwgreg.src_addr & mystique->vram_mask] << count);
+
+ if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0])
+ {
+ mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5];
+ mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5];
+ mystique->dwgreg.src_addr = mystique->dwgreg.ar[3];
+ }
+ else
+ mystique->dwgreg.src_addr++;
+
+ if (mystique->dwgreg.xdst == mystique->dwgreg.fxright)
+ {
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.length_cur--;
+ if (!mystique->dwgreg.length_cur)
+ {
+ mystique->busy = 0;
+ mystique->blitter_complete_refcount++;
+ break;
+ }
+ break;
+ }
+ else
+ mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff;
+
+ count += 8;
+ }
+ break;
+
+ case MACCESS_PWIDTH_16:
+ // pclog(" IDUMP %08x\n", mystique->dwgreg.src_addr);
+ while (count < 32)
+ {
+ val |= (((uint16_t *)svga->vram)[mystique->dwgreg.src_addr & mystique->vram_mask_w] << count);
+
+ if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0])
+ {
+ mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5];
+ mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5];
+ mystique->dwgreg.src_addr = mystique->dwgreg.ar[3];
+ }
+ else
+ mystique->dwgreg.src_addr++;
+
+ if (mystique->dwgreg.xdst == mystique->dwgreg.fxright)
+ {
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.length_cur--;
+ if (!mystique->dwgreg.length_cur)
+ {
+ mystique->busy = 0;
+ mystique->blitter_complete_refcount++;
+ break;
+ }
+ break;
+ }
+ else
+ mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff;
+
+ count += 16;
+ }
+ break;
+
+ case MACCESS_PWIDTH_24:
+ if (mystique->dwgreg.idump_end_of_line)
+ {
+ mystique->dwgreg.idump_end_of_line = 0;
+ val = mystique->dwgreg.iload_rem_data;
+ mystique->dwgreg.iload_rem_count = 0;
+ mystique->dwgreg.iload_rem_data = 0;
+ if (!mystique->dwgreg.length_cur)
+ {
+ mystique->busy = 0;
+ mystique->blitter_complete_refcount++;
+ }
+ break;
+ }
+
+ count += mystique->dwgreg.iload_rem_count;
+ val64 = mystique->dwgreg.iload_rem_data;
+
+// pclog(" IDUMP %08x\n", mystique->dwgreg.src_addr);
+ while ((count < 32) && !mystique->dwgreg.idump_end_of_line)
+ {
+ val64 |= (uint64_t)((*(uint32_t *)&svga->vram[(mystique->dwgreg.src_addr * 3) & mystique->vram_mask]) & 0xffffff) << count;
+/* pclog(" %i %i %i %016llx\n", count, mystique->dwgreg.xdst,
+ mystique->dwgreg.length_cur, val64);*/
+
+ if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0])
+ {
+ mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5];
+ mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5];
+ mystique->dwgreg.src_addr = mystique->dwgreg.ar[3];
+ }
+ else
+ mystique->dwgreg.src_addr++;
+
+ if (mystique->dwgreg.xdst == mystique->dwgreg.fxright)
+ {
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.length_cur--;
+ if (!mystique->dwgreg.length_cur)
+ {
+ if (count > 8)
+ mystique->dwgreg.idump_end_of_line = 1;
+ else
+ {
+ count = 32;
+ mystique->busy = 0;
+ mystique->blitter_complete_refcount++;
+ }
+ break;
+ }
+ if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_LINEAR))
+ {
+ if (count > 8)
+ mystique->dwgreg.idump_end_of_line = 1;
+ else
+ {
+ count = 32;
+ break;
+ }
+ }
+ }
+ else
+ mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff;
+
+ count += 24;
+ }
+ if (count > 32)
+ mystique->dwgreg.iload_rem_count = count - 32;
+ else
+ mystique->dwgreg.iload_rem_count = 0;
+ mystique->dwgreg.iload_rem_data = (uint32_t)(val64 >> 32);
+ val = val64 & 0xffffffff;
+ break;
+
+ case MACCESS_PWIDTH_32:
+// pclog(" IDUMP %08x\n", mystique->dwgreg.src_addr);
+
+ val = (((uint32_t *)svga->vram)[mystique->dwgreg.src_addr & mystique->vram_mask_l] << count);
+
+ if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0])
+ {
+ mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5];
+ mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5];
+ mystique->dwgreg.src_addr = mystique->dwgreg.ar[3];
+ }
+ else
+ mystique->dwgreg.src_addr++;
+
+ if (mystique->dwgreg.xdst == mystique->dwgreg.fxright)
+ {
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.length_cur--;
+ if (!mystique->dwgreg.length_cur)
+ {
+ mystique->busy = 0;
+ mystique->blitter_complete_refcount++;
+ break;
+ }
+ break;
+ }
+ else
+ mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff;
+ break;
+
+ default:
+ fatal("IDUMP DWGCTRL_BLTMOD_BU32RGB %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->maccess_running);
+ }
+ break;
+
+ default:
+ fatal("IDUMP DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running);
+ break;
+ }
+ break;
+
+ default:
+ fatal("Unknown IDUMP atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+
+ return val;
+}
+
+static uint32_t blit_idump_read(mystique_t *mystique)
+{
+ uint32_t ret = 0xffffffff;
+
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK)
+ {
+ case DWGCTRL_OPCODE_IDUMP:
+ ret = blit_idump_idump(mystique);
+ break;
+
+ default:
+ fatal("blit_idump_read: bad opcode %08x\n", mystique->dwgreg.dwgctrl_running);
+ }
+
+// pclog(" idump returned %08x\n", ret);
+ return ret;
+}
+
+static void blit_iload_iload(mystique_t *mystique, uint32_t data, int size)
+{
+ svga_t *svga = &mystique->svga;
+ uint32_t src, dst;
+ uint64_t data64;
+ int min_size;
+ uint32_t bltckey = mystique->dwgreg.fcol, bltcmsk = mystique->dwgreg.bcol;
+ const int transc = mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC;
+ const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT;
+ uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4];
+ uint32_t data_mask = 1;
+
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_8:
+ bltckey &= 0xff;
+ bltcmsk &= 0xff;
+ break;
+ case MACCESS_PWIDTH_16:
+ bltckey &= 0xffff;
+ bltcmsk &= 0xffff;
+ break;
+ }
+
+ mystique->dwgreg.words++;
+// pclog("blit_iload_iload: %08x %06x %02x %i %08x words=%i %08x %08x\n", data, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst, data, (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) == DWGCTRL_BLTMOD_BMONOWF, mystique->dwgreg.dwgctrl_running, mystique->dwgreg.words,mystique->dwgreg.words, mystique->maccess_running);
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK)
+ {
+ case DWGCTRL_ATYPE_RPL:
+ if (mystique->maccess_running & MACCESS_TLUTLOAD)
+ {
+ while ((mystique->dwgreg.length_cur > 0) && (size >= 16))
+ {
+ uint16_t src = data & 0xffff;
+// pclog(" LUT[%02x]=%04x\n", mystique->dwgreg.ydst & 0xff, src);
+
+ mystique->lut[mystique->dwgreg.ydst & 0xff].r = (src >> 11) << 3;
+ mystique->lut[mystique->dwgreg.ydst & 0xff].g = ((src >> 5) & 0x3f) << 2;
+ mystique->lut[mystique->dwgreg.ydst & 0xff].b = (src & 0x1f) << 3;
+ mystique->dwgreg.ydst++;
+ mystique->dwgreg.length_cur--;
+ data >>= 16;
+ size -= 16;
+ }
+
+ if (!mystique->dwgreg.length_cur)
+ {
+ mystique->busy = 0;
+ mystique->blitter_complete_refcount++;
+ }
+ break;
+ }
+ case DWGCTRL_ATYPE_RSTR:
+ case DWGCTRL_ATYPE_BLK:
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK)
+ {
+ case DWGCTRL_BLTMOD_BFCOL:
+ size += mystique->dwgreg.iload_rem_count;
+// pclog(" size=%i xdst=%i cur=%i data= %08x %08x ", size, mystique->dwgreg.xdst, mystique->dwgreg.length_cur, mystique->dwgreg.iload_rem_data, data);
+ data64 = mystique->dwgreg.iload_rem_data | ((uint64_t)data << mystique->dwgreg.iload_rem_count);
+// pclog("%016llx words=%i\n", data64, mystique->dwgreg.words);
+
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_8:
+ min_size = 8;
+ break;
+ case MACCESS_PWIDTH_16:
+ min_size = 16;
+ break;
+ case MACCESS_PWIDTH_24:
+ min_size = 24;
+ break;
+ case MACCESS_PWIDTH_32:
+ min_size = 32;
+ break;
+ }
+
+ while (size >= min_size)
+ {
+ int draw = (!transc || (data & bltcmsk) != bltckey) && trans[mystique->dwgreg.xdst & 3];
+
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_8:
+ if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw)
+ {
+ dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask];
+
+ dst = bitop(data & 0xff, dst, mystique->dwgreg.dwgctrl_running);
+// pclog(" 8 %06x=%04x\n", mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst, dst);
+ svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask) >> 12] = changeframecount;
+ }
+/* else
+ pclog(" Clipped %i,%i %i %08x,%08x %08x\n",
+ mystique->dwgreg.cxleft, mystique->dwgreg.cxright, mystique->dwgreg.xdst,
+ mystique->dwgreg.ytop, mystique->dwgreg.ybot, mystique->dwgreg.ydst_lin);*/
+
+ data >>= 8;
+ size -= 8;
+ break;
+
+ case MACCESS_PWIDTH_16:
+ if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw)
+ {
+ dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w];
+
+ dst = bitop(data & 0xffff, dst, mystique->dwgreg.dwgctrl_running);
+// pclog(" 16 %06x=%04x\n", mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst, dst);
+ ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount;
+ }
+
+ data >>= 16;
+ size -= 16;
+ break;
+
+ case MACCESS_PWIDTH_24:
+ if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot)
+ {
+ uint32_t old_dst = *((uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]);
+
+ dst = bitop(data64, old_dst, mystique->dwgreg.dwgctrl_running);
+ *((uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]) = (dst & 0xffffff) | (old_dst & 0xff000000);
+ svga->changedvram[(((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask) >> 12] = changeframecount;
+ }
+
+ data64 >>= 24;
+ size -= 24;
+ break;
+
+ case MACCESS_PWIDTH_32:
+ if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw)
+ {
+ dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l];
+
+ dst = bitop(data, dst, mystique->dwgreg.dwgctrl_running);
+// pclog(" 32 %06x=%04x\n", mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst, dst);
+ ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount;
+ }
+
+ size = 0;
+ break;
+
+ default:
+ fatal("ILOAD RSTR/RPL BFCOL pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK);
+ }
+
+ if (mystique->dwgreg.xdst == mystique->dwgreg.fxright)
+ {
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK);
+ mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7;
+ mystique->dwgreg.length_cur--;
+ if (!mystique->dwgreg.length_cur)
+ {
+ mystique->busy = 0;
+ mystique->blitter_complete_refcount++;
+ break;
+ }
+ data64 = 0;
+ size = 0;
+ break;
+ }
+ else
+ mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff;
+ }
+ mystique->dwgreg.iload_rem_count = size;
+ mystique->dwgreg.iload_rem_data = data64;
+ break;
+
+ case DWGCTRL_BLTMOD_BMONOWF:
+ data = (data >> 24) | ((data & 0x00ff0000) >> 8) | ((data & 0x0000ff00) << 8) | (data << 24);
+ data_mask = (1 << 31);
+ case DWGCTRL_BLTMOD_BMONOLEF:
+ while (size)
+ {
+ if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot &&
+ ((data & data_mask) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) &&
+ trans[mystique->dwgreg.xdst & 3])
+ {
+ uint32_t old_dst;
+
+ src = (data & data_mask) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol;
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_8:
+ dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask];
+
+// pclog(" %02x %02x %06x ", src, dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst);
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);
+// pclog("%02x\n", dst);
+
+ svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_16:
+ dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w];
+
+// pclog(" %02x %02x %06x ", src, dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst);
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);
+// pclog("%02x\n", dst);
+
+ ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_24:
+ old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask];
+
+// pclog(" %02x %02x %06x ", src, old_dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst);
+ dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running);
+// pclog("%02x %08x %08x %08x %i\n", dst, data, mystique->dwgreg.fcol, mystique->dwgreg.bcol, mystique->dwgreg.xdst);
+
+ *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000);
+ svga->changedvram[(((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_32:
+ dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l];
+
+// pclog(" %02x %02x %06x ", src, dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst);
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);
+// pclog("%02x %08x %08x %08x %i\n", dst, data, mystique->dwgreg.fcol, mystique->dwgreg.bcol, mystique->dwgreg.xdst);
+
+ ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount;
+ break;
+
+ default:
+ fatal("ILOAD RSTR/RPL BMONOWF pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK);
+ }
+ }
+
+ if (mystique->dwgreg.xdst == mystique->dwgreg.fxright)
+ {
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK);
+ mystique->dwgreg.length_cur--;
+ if (!mystique->dwgreg.length_cur)
+ {
+ mystique->busy = 0;
+ mystique->blitter_complete_refcount++;
+ break;
+ }
+ if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_LINEAR))
+ break;
+ }
+ else
+ mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff;
+ if (data_mask == 1)
+ data >>= 1;
+ else
+ data <<= 1;
+ size--;
+ }
+ break;
+
+ case DWGCTRL_BLTMOD_BU24RGB:
+ size += mystique->dwgreg.iload_rem_count;
+// pclog(" size=%i data= %08x %08x ", size, mystique->dwgreg.iload_rem_data, data);
+ data64 = mystique->dwgreg.iload_rem_data | ((uint64_t)data << mystique->dwgreg.iload_rem_count);
+// pclog("%016llx\n", data64);
+
+ while (size >= 24)
+ {
+ if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot)
+ {
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_32:
+ dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l];
+
+// pclog(" %06llx %02x %06x ", data64 & 0xffffff, dst, mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst);
+// pclog("x=%i l=%i ", mystique->dwgreg.xdst, mystique->dwgreg.length_cur);
+ dst = bitop(data64 & 0xffffff, dst, mystique->dwgreg.dwgctrl_running);
+// pclog("%02x\n", dst);
+
+ ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount;
+ break;
+
+ default:
+ fatal("ILOAD RSTR/RPL BU24RGB pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK);
+ }
+ }
+
+ data64 >>= 24;
+ size -= 24;
+ if (mystique->dwgreg.xdst == mystique->dwgreg.fxright)
+ {
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK);
+ mystique->dwgreg.length_cur--;
+ if (!mystique->dwgreg.length_cur)
+ {
+ mystique->busy = 0;
+ mystique->blitter_complete_refcount++;
+ break;
+ }
+ data64 = 0;
+ size = 0;
+ break;
+ }
+ else
+ mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff;
+ }
+
+ mystique->dwgreg.iload_rem_count = size;
+ mystique->dwgreg.iload_rem_data = data64;
+ break;
+
+ default:
+ fatal("ILOAD DWGCTRL_ATYPE_RPL\n");
+ break;
+ }
+ break;
+
+ default:
+ fatal("Unknown ILOAD iload atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+}
+
+#define CLAMP(x) do \
+ { \
+ if ((x) & ~0xff) \
+ x = ((x) < 0) ? 0 : 0xff; \
+ } \
+ while (0)
+
+static void blit_iload_iload_scale(mystique_t *mystique, uint32_t data, int size)
+{
+ svga_t *svga = &mystique->svga;
+ uint64_t data64 = 0;
+ int y0, y1;
+ int u, v;
+ int dR, dG, dB;
+ int r0, g0, b0;
+ int r1, g1, b1;
+
+// pclog(" iload_scale: data=%08x\n", data);
+
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK)
+ {
+ case DWGCTRL_BLTMOD_BUYUV:
+ y0 = (298 * ((int)(data & 0xff) - 16)) >> 8;
+ u = ((data >> 8) & 0xff) - 0x80;
+ y1 = (298 * ((int)((data >> 16) & 0xff) - 16)) >> 8;
+ v = ((data >> 24) & 0xff) - 0x80;
+
+ dR = (309*v) >> 8;
+ dG = (100*u + 208*v) >> 8;
+ dB = (516*u) >> 8;
+
+ r0 = y0 + dR;
+ CLAMP(r0);
+ g0 = y0 - dG;
+ CLAMP(g0);
+ b0 = y0 + dB;
+ CLAMP(b0);
+ r1 = y1 + dR;
+ CLAMP(r1);
+ g1 = y1 - dG;
+ CLAMP(g1);
+ b1 = y1 + dB;
+ CLAMP(b1);
+
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_16:
+ data = (b0 >> 3) | ((g0 >> 2) << 5) | ((r0 >> 3) << 11);
+ data |= (((b1 >> 3) | ((g1 >> 2) << 5) | ((r1 >> 3) << 11)) << 16);
+ size = 32;
+ break;
+ case MACCESS_PWIDTH_32:
+ data64 = b0 | (g0 << 8) | (r0 << 16);
+ data64 |= ((uint64_t)b0 << 32) | ((uint64_t)g0 << 40) | ((uint64_t)r0 << 48);
+ size = 64;
+ break;
+
+ default:
+ fatal("blit_iload_iload_scale BUYUV pwidth %i\n", mystique->maccess_running & MACCESS_PWIDTH_MASK);
+ }
+ break;
+
+ default:
+ fatal("blit_iload_iload_scale bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK);
+ break;
+ }
+
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_16:
+ while (size >= 16)
+ {
+// pclog(" Write %i %i %08x\n", mystique->dwgreg.xdst, mystique->dwgreg.fxright, mystique->dwgreg.ar[6]);
+ if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot)
+ {
+ uint16_t dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w];
+ dst = bitop(data & 0xffff, dst, mystique->dwgreg.dwgctrl_running);
+ ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount;
+ }
+
+ mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2];
+ if ((int32_t)mystique->dwgreg.ar[6] >= 0)
+ {
+ mystique->dwgreg.ar[6] -= (mystique->dwgreg.fxright - mystique->dwgreg.fxleft);
+ data >>= 16;
+ size -= 16;
+ }
+
+ if (mystique->dwgreg.xdst == mystique->dwgreg.fxright)
+ {
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK);
+ mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft);
+ mystique->dwgreg.length_cur--;
+ if (!mystique->dwgreg.length_cur)
+ {
+ mystique->busy = 0;
+ mystique->blitter_complete_refcount++;
+ break;
+ }
+ break;
+ }
+ else
+ mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff;
+ }
+ break;
+
+ case MACCESS_PWIDTH_32:
+ while (size >= 32)
+ {
+// pclog(" Write %i %i %08x\n", mystique->dwgreg.xdst, mystique->dwgreg.fxright, mystique->dwgreg.ar[6]);
+ if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot)
+ {
+ uint32_t dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l];
+ dst = bitop(data64, dst, mystique->dwgreg.dwgctrl_running);
+ ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount;
+ }
+
+ mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2];
+ if ((int32_t)mystique->dwgreg.ar[6] >= 0)
+ {
+ mystique->dwgreg.ar[6] -= (mystique->dwgreg.fxright - mystique->dwgreg.fxleft);
+ data64 >>= 32;
+ size -= 32;
+ }
+
+ if (mystique->dwgreg.xdst == mystique->dwgreg.fxright)
+ {
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK);
+ mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft);
+ mystique->dwgreg.length_cur--;
+ if (!mystique->dwgreg.length_cur)
+ {
+ mystique->busy = 0;
+ mystique->blitter_complete_refcount++;
+ break;
+ }
+ break;
+ }
+ else
+ mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff;
+ }
+ break;
+
+ default:
+ fatal("ILOAD_SCALE pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK);
+ }
+}
+
+static void blit_iload_iload_high(mystique_t *mystique, uint32_t data, int size)
+{
+ svga_t *svga = &mystique->svga;
+ uint32_t out_data;
+ int y0, y1, u, v;
+ int dR, dG, dB;
+ int r = 0, g = 0, b = 0;
+ int next_r = 0, next_g = 0, next_b = 0;
+
+// pclog(" iload_high: data=%08x\n", data);
+
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK)
+ {
+ case DWGCTRL_BLTMOD_BUYUV:
+ y0 = (298 * ((int)(data & 0xff) - 16)) >> 8;
+ u = ((data >> 8) & 0xff) - 0x80;
+ y1 = (298 * ((int)((data >> 16) & 0xff) - 16)) >> 8;
+ v = ((data >> 24) & 0xff) - 0x80;
+
+ dR = (309*v) >> 8;
+ dG = (100*u + 208*v) >> 8;
+ dB = (516*u) >> 8;
+
+ r = y0 + dR;
+ CLAMP(r);
+ g = y0 - dG;
+ CLAMP(g);
+ b = y0 + dB;
+ CLAMP(b);
+
+ next_r = y1 + dR;
+ CLAMP(next_r);
+ next_g = y1 - dG;
+ CLAMP(next_g);
+ next_b = y1 + dB;
+ CLAMP(next_b);
+
+ size = 32;
+ break;
+
+ default:
+ fatal("blit_iload_iload_high bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK);
+ break;
+ }
+
+ while (size >= 16)
+ {
+ if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot)
+ {
+ uint32_t dst;
+ int f1 = (mystique->dwgreg.ar[6] >> 12) & 0xf;
+ int f0 = 0x10 - f1;
+ int out_r = ((mystique->dwgreg.lastpix_r * f0) + (r * f1)) >> 4;
+ int out_g = ((mystique->dwgreg.lastpix_g * f0) + (g * f1)) >> 4;
+ int out_b = ((mystique->dwgreg.lastpix_b * f0) + (b * f1)) >> 4;
+
+// pclog(" Write %i %i %08x %i %i %i %i %i\n", mystique->dwgreg.xdst, mystique->dwgreg.fxright, mystique->dwgreg.ar[6], mystique->dwgreg.lastpix_r, r, f0, f1, out_r);
+
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_16:
+ out_data = (out_b >> 3) | ((out_g >> 2) << 5) | ((out_r >> 3) << 11);
+ dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w];
+ dst = bitop(out_data, dst, mystique->dwgreg.dwgctrl_running);
+ ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount;
+ break;
+ case MACCESS_PWIDTH_32:
+ out_data = out_b | (out_g << 8) | (out_r << 16);
+ dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l];
+ dst = bitop(out_data, dst, mystique->dwgreg.dwgctrl_running);
+ ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount;
+ break;
+
+ default:
+ fatal("ILOAD_SCALE_HIGH RSTR/RPL BUYUV pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK);
+ }
+ }
+
+ mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2];
+ if ((int32_t)mystique->dwgreg.ar[6] >= 0)
+ {
+ mystique->dwgreg.ar[6] -= 65536;
+ size -= 16;
+
+ mystique->dwgreg.lastpix_r = r;
+ mystique->dwgreg.lastpix_g = g;
+ mystique->dwgreg.lastpix_b = b;
+ r = next_r;
+ g = next_g;
+ b = next_b;
+ }
+
+ if (mystique->dwgreg.xdst == mystique->dwgreg.fxright)
+ {
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK);
+ mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft);
+ mystique->dwgreg.lastpix_r = 0;
+ mystique->dwgreg.lastpix_g = 0;
+ mystique->dwgreg.lastpix_b = 0;
+
+ mystique->dwgreg.length_cur--;
+ if (!mystique->dwgreg.length_cur)
+ {
+ mystique->busy = 0;
+ mystique->blitter_complete_refcount++;
+ break;
+ }
+ break;
+ }
+ else
+ mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff;
+ }
+}
+
+static void blit_iload_iload_highv(mystique_t *mystique, uint32_t data, int size)
+{
+ uint8_t *src0, *src1;
+
+// pclog(" iload_highv: data=%08x\n", data);
+
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK)
+ {
+ case DWGCTRL_BLTMOD_BUYUV:
+ if (!mystique->dwgreg.highv_line)
+ {
+ mystique->dwgreg.highv_data = data;
+ mystique->dwgreg.highv_line = 1;
+ return;
+ }
+ mystique->dwgreg.highv_line = 0;
+
+ src0 = (uint8_t *)&mystique->dwgreg.highv_data;
+ src1 = (uint8_t *)&data;
+
+ src1[0] = ((src0[0] * mystique->dwgreg.beta) + (src1[0] * (16 - mystique->dwgreg.beta))) >> 4;
+ src1[1] = ((src0[1] * mystique->dwgreg.beta) + (src1[1] * (16 - mystique->dwgreg.beta))) >> 4;
+ src1[2] = ((src0[2] * mystique->dwgreg.beta) + (src1[2] * (16 - mystique->dwgreg.beta))) >> 4;
+ src1[3] = ((src0[3] * mystique->dwgreg.beta) + (src1[3] * (16 - mystique->dwgreg.beta))) >> 4;
+ blit_iload_iload_high(mystique, data, 32);
+ break;
+
+ default:
+ fatal("blit_iload_iload_highv bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK);
+ break;
+ }
+}
+
+static void blit_iload_write(mystique_t *mystique, uint32_t data, int size)
+{
+// pclog(" ILOAD %08x %08x\n", data, mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK);
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK)
+ {
+ case DWGCTRL_OPCODE_ILOAD:
+ blit_iload_iload(mystique, data, size);
+ break;
+
+ case DWGCTRL_OPCODE_ILOAD_SCALE:
+ blit_iload_iload_scale(mystique, data, size);
+ break;
+
+ case DWGCTRL_OPCODE_ILOAD_HIGH:
+ blit_iload_iload_high(mystique, data, size);
+ break;
+
+ case DWGCTRL_OPCODE_ILOAD_HIGHV:
+ blit_iload_iload_highv(mystique, data, size);
+ break;
+
+ default:
+ fatal("blit_iload_write: bad opcode %08x\n", mystique->dwgreg.dwgctrl_running);
+ }
+}
+
+static int z_check(uint16_t z, uint16_t old_z, uint32_t z_mode)//mystique->dwgreg.dwgctrl & DWGCTRL_ZMODE_MASK)
+{
+ switch (z_mode)
+ {
+ case DWGCTRL_ZMODE_ZE:
+ return (z == old_z);
+ case DWGCTRL_ZMODE_ZNE:
+ return (z != old_z);
+ case DWGCTRL_ZMODE_ZLT:
+ return (z < old_z);
+ case DWGCTRL_ZMODE_ZLTE:
+ return (z <= old_z);
+ case DWGCTRL_ZMODE_ZGT:
+ return (z > old_z);
+ case DWGCTRL_ZMODE_ZGTE:
+ return (z >= old_z);
+
+ case DWGCTRL_ZMODE_NOZCMP:
+ default:
+ return 1;
+ }
+}
+
+static void blit_line(mystique_t *mystique, int closed)
+{
+ svga_t *svga = &mystique->svga;
+ uint32_t src, dst, old_dst;
+ int x;
+ int z_write;
+
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK)
+ {
+ case DWGCTRL_ATYPE_RSTR:
+ case DWGCTRL_ATYPE_RPL:
+ x = mystique->dwgreg.xdst;
+ while (mystique->dwgreg.length > 0)
+ {
+ if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot)
+ {
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_8:
+ src = mystique->dwgreg.fcol;
+ dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask];
+
+// pclog(" LINE %i %08x %08x\n", x, mystique->dwgreg.ydst_lin, mystique->dwgreg.ar[1]);
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);
+ svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_16:
+ src = mystique->dwgreg.fcol;
+ dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w];
+
+// pclog(" LINE %i %08x %08x\n", x, mystique->dwgreg.ydst_lin, mystique->dwgreg.ar[1]);
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);
+ ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_24:
+ src = mystique->dwgreg.fcol;
+ old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask];
+
+// pclog(" LINE %i %08x %08x\n", x, mystique->dwgreg.ydst_lin, mystique->dwgreg.ar[1]);
+ dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running);
+ *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000);
+ svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_32:
+ src = mystique->dwgreg.fcol;
+ dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l];
+
+// pclog(" LINE %i %08x %08x\n", x, mystique->dwgreg.ydst_lin, mystique->dwgreg.ar[1]);
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);
+ ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount;
+ break;
+
+ default:
+ fatal("LINE RSTR/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+ }
+
+ if (mystique->dwgreg.sgn.sdydxl)
+ x += (mystique->dwgreg.sgn.sdxl ? -1 : 1);
+ else
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK));
+
+ if ((int32_t)mystique->dwgreg.ar[1] >= 0)
+ {
+ mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2];
+
+ if (mystique->dwgreg.sgn.sdydxl)
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK));
+ else
+ x += (mystique->dwgreg.sgn.sdxl ? -1 : 1);
+ }
+ else
+ mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0];
+
+ mystique->dwgreg.length--;
+ }
+ break;
+
+ case DWGCTRL_ATYPE_I:
+ case DWGCTRL_ATYPE_ZI:
+ z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI);
+ x = mystique->dwgreg.xdst;
+ while (mystique->dwgreg.length > 0)
+ {
+ if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot)
+ {
+ uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15);
+ uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask];
+ uint16_t old_z = z_p[x];
+
+ if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK))
+ {
+ int r = 0, g = 0, b = 0;
+
+ if (z_write)
+ z_p[x] = z;
+
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_16:
+ if (!(mystique->dwgreg.dr[4] & (1 << 23)))
+ r = (mystique->dwgreg.dr[4] >> 18) & 0x1f;
+ if (!(mystique->dwgreg.dr[8] & (1 << 23)))
+ g = (mystique->dwgreg.dr[8] >> 17) & 0x3f;
+ if (!(mystique->dwgreg.dr[12] & (1 << 23)))
+ b = (mystique->dwgreg.dr[12] >> 18) & 0x1f;
+ dst = (r << 11) | (g << 5) | b;
+
+ ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount;
+ break;
+
+ default:
+ fatal("LINE I/ZI PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+ }
+ }
+
+ if (mystique->dwgreg.sgn.sdydxl)
+ x += (mystique->dwgreg.sgn.sdxl ? -1 : 1);
+ else
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK));
+
+ mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2];
+ mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6];
+ mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10];
+ mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14];
+
+ if ((int32_t)mystique->dwgreg.ar[1] >= 0)
+ {
+ mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2];
+
+ if (mystique->dwgreg.sgn.sdydxl)
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK));
+ else
+ x += (mystique->dwgreg.sgn.sdxl ? -1 : 1);
+
+ mystique->dwgreg.dr[0] += mystique->dwgreg.dr[3];
+ mystique->dwgreg.dr[4] += mystique->dwgreg.dr[7];
+ mystique->dwgreg.dr[8] += mystique->dwgreg.dr[11];
+ mystique->dwgreg.dr[12] += mystique->dwgreg.dr[15];
+ }
+ else
+ mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0];
+
+ mystique->dwgreg.length--;
+ }
+ break;
+
+
+ default:
+ fatal("Unknown atype %03x %08x LINE\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+ mystique->blitter_complete_refcount++;
+}
+
+static void blit_autoline(mystique_t *mystique, int closed)
+{
+ int start_x = (int32_t)mystique->dwgreg.ar[5];
+ int start_y = (int32_t)mystique->dwgreg.ar[6];
+ int end_x = (int32_t)mystique->dwgreg.ar[0];
+ int end_y = (int32_t)mystique->dwgreg.ar[2];
+ int dx = end_x - start_x;
+ int dy = end_y - start_y;
+
+ if (ABS(dx) > ABS(dy))
+ {
+ mystique->dwgreg.sgn.sdydxl = 1;
+ mystique->dwgreg.ar[0] = 2*ABS(dy);
+ mystique->dwgreg.ar[1] = 2*ABS(dy) - ABS(dx) - ((start_y > end_y) ? 1 : 0);
+ mystique->dwgreg.ar[2] = 2*ABS(dy) - 2*ABS(dx);
+ mystique->dwgreg.length = ABS(end_x - start_x);
+ }
+ else
+ {
+ mystique->dwgreg.sgn.sdydxl = 0;
+ mystique->dwgreg.ar[0] = 2*ABS(dx);
+ mystique->dwgreg.ar[1] = 2*ABS(dx) - ABS(dy) - ((start_y > end_y) ? 1 : 0);
+ mystique->dwgreg.ar[2] = 2*ABS(dx) - 2*ABS(dy);
+ mystique->dwgreg.length = ABS(end_y - start_y);
+ }
+ mystique->dwgreg.sgn.sdxl = (start_x > end_x) ? 1 : 0;
+ mystique->dwgreg.sgn.sdy = (start_y > end_y) ? 1 : 0;
+
+
+/* pclog("Autoline %s\n", closed ? "closed" : "open");
+ pclog("Start %i,%i\n", start_x, start_y);
+ pclog("End %i,%i\n", end_x, end_y);
+ pclog("SGN=%x\n", mystique->dwgreg.sgn);
+ pclog("AR0=%08x AR1=%08x AR2=%08x\n", mystique->dwgreg.ar[0],
+ mystique->dwgreg.ar[1],
+ mystique->dwgreg.ar[2]);
+ pclog("Length %i\n", mystique->dwgreg.length);*/
+ blit_line(mystique, closed);
+
+ mystique->dwgreg.ar[5] = end_x;
+ mystique->dwgreg.xdst = end_x;
+ mystique->dwgreg.ar[6] = end_y;
+ mystique->dwgreg.ydst = end_y;
+ mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg;
+}
+
+static void blit_trap(mystique_t *mystique)
+{
+ svga_t *svga = &mystique->svga;
+ uint32_t z_back, r_back, g_back, b_back;
+ int z_write;
+ int y;
+ const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT;
+
+ mystique->trap_count++;
+
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK)
+ {
+ case DWGCTRL_ATYPE_BLK:
+ case DWGCTRL_ATYPE_RPL:
+ //fxleft, fxright
+ //fcol
+/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright);
+ pclog("fcol=%08x\n", mystique->dwgreg.fcol);
+ pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length);
+ pclog("pitch=%08x\n", mystique->dwgreg.pitch);
+ pclog("ydst_lin=%08x\n", mystique->dwgreg.ydst_lin);*/
+// if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_SGNZERO))
+// fatal("Not rectangle\n");
+
+ for (y = 0; y < mystique->dwgreg.length; y++)
+ {
+ uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4];
+ int16_t x_l = mystique->dwgreg.fxleft & 0xffff;
+ int16_t x_r = mystique->dwgreg.fxright & 0xffff;
+ int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7;
+
+// pclog(" line %03i: %08x\n", y, mystique->dwgreg.ydst_lin);
+ while (x_l != x_r)
+ {
+ if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot &&
+ trans[x_l & 3])
+ {
+ int xoff = (mystique->dwgreg.xoff + x_l) & 7;
+ int pattern = mystique->dwgreg.pattern[yoff][xoff];
+ uint32_t dst;
+
+// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff);
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_8:
+ svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] =
+ (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xff;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_16:
+ ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] =
+ (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffff;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_24:
+ dst = *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) & 0xff000000;
+ *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) =
+ ((pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffffff) | dst;
+ svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_32:
+ ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] =
+ pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount;
+ break;
+
+ default:
+ fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+ }
+ x_l++;
+ mystique->pixel_count++;
+ }
+
+ if ((int32_t)mystique->dwgreg.ar[1] < 0)
+ {
+ while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0])
+ {
+ mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0];
+ mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1);
+ }
+ }
+ else
+ mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2];
+
+ if ((int32_t)mystique->dwgreg.ar[4] < 0)
+ {
+ while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6])
+ {
+ mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6];
+ mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1);
+ }
+ }
+ else
+ mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5];
+
+ mystique->dwgreg.ydst++;
+ mystique->dwgreg.ydst &= 0x7fffff;
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK);
+
+ mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7;
+ }
+ break;
+
+ case DWGCTRL_ATYPE_RSTR:
+ for (y = 0; y < mystique->dwgreg.length; y++)
+ {
+ uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4];
+ int16_t x_l = mystique->dwgreg.fxleft & 0xffff;
+ int16_t x_r = mystique->dwgreg.fxright & 0xffff;
+ int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7;
+
+// pclog(" line %03i: %08x\n", y, mystique->dwgreg.ydst_lin);
+ while (x_l != x_r)
+ {
+ if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot &&
+ trans[x_l & 3])
+ {
+ int xoff = (mystique->dwgreg.xoff + x_l) & 7;
+ int pattern = mystique->dwgreg.pattern[yoff][xoff];
+ uint32_t src = pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol;
+ uint32_t dst, old_dst;
+
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_8:
+ dst = svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask];
+
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);
+// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff);
+ svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_16:
+ dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w];
+
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);
+// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff);
+ ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_24:
+ old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask];
+
+ dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running);
+// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff);
+ *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000);
+ svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_32:
+ dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l];
+
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);
+// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff);
+ ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount;
+ break;
+
+ default:
+ fatal("TRAP RSTR PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+ }
+ x_l++;
+ mystique->pixel_count++;
+ }
+
+ if ((int32_t)mystique->dwgreg.ar[1] < 0)
+ {
+ while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0])
+ {
+ mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0];
+ mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1);
+ }
+ }
+ else
+ mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2];
+
+ if ((int32_t)mystique->dwgreg.ar[4] < 0)
+ {
+ while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6])
+ {
+ mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6];
+ mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1);
+ }
+ }
+ else
+ mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5];
+
+ mystique->dwgreg.ydst++;
+ mystique->dwgreg.ydst &= 0x7fffff;
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK);
+
+ mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7;
+ }
+ break;
+
+ case DWGCTRL_ATYPE_I:
+ case DWGCTRL_ATYPE_ZI:
+ z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI);
+/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright);
+ pclog("fcol=%08x\n", mystique->dwgreg.fcol);
+ pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length);
+ pclog("pitch=%08x\n", mystique->dwgreg.pitch);
+ pclog("ydst_lin=%08x\n", mystique->dwgreg.ydst_lin);
+ pclog("trap! maccess=%08x %08x %08x %08x\n", mystique->maccess_running, mystique->dwgreg.dr[4], mystique->dwgreg.dr[8], mystique->dwgreg.dr[12]);*/
+
+ for (y = 0; y < mystique->dwgreg.length; y++)
+ {
+ uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4];
+ uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask];
+ int16_t x_l = mystique->dwgreg.fxleft & 0xffff;
+ int16_t x_r = mystique->dwgreg.fxright & 0xffff;
+ int16_t old_x_l = x_l;
+ int dx;
+
+ z_back = mystique->dwgreg.dr[0];
+ r_back = mystique->dwgreg.dr[4];
+ g_back = mystique->dwgreg.dr[8];
+ b_back = mystique->dwgreg.dr[12];
+
+// pclog(" line %03i: %08x\n", y, mystique->dwgreg.ydst_lin);
+ while (x_l != x_r)
+ {
+ if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot &&
+ trans[x_l & 3])
+ {
+ uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15);
+ uint16_t old_z = z_p[x_l];
+
+ if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK))
+ {
+ uint32_t dst = 0, old_dst;
+ int r = 0, g = 0, b = 0;
+
+ if (!(mystique->dwgreg.dr[4] & (1 << 23)))
+ r = (mystique->dwgreg.dr[4] >> 15) & 0xff;
+ if (!(mystique->dwgreg.dr[8] & (1 << 23)))
+ g = (mystique->dwgreg.dr[8] >> 15) & 0xff;
+ if (!(mystique->dwgreg.dr[12] & (1 << 23)))
+ b = (mystique->dwgreg.dr[12] >> 15) & 0xff;
+
+ if (z_write)
+ z_p[x_l] = z;
+
+// pclog(" %06x %02x\n", mystique->dwgreg.ydst_lin + x, mystique->dwgreg.fcol & 0xff);
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_8:
+ svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_16:
+ dst = dither(mystique, r, g, b, x_l & 1, mystique->dwgreg.selline & 1);
+// pclog(" %08x %08x %08x %04x\n", mystique->dwgreg.dr[4], mystique->dwgreg.dr[8], mystique->dwgreg.dr[12], dst);
+ ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_24:
+ old_dst = *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) & 0xff000000;
+ *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) = old_dst | dst;
+ svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_32:
+ ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = b | (g << 8) | (r << 16);
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount;
+ break;
+
+ default:
+ fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+ }
+ }
+
+ mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2];
+ mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6];
+ mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10];
+ mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14];
+
+ x_l++;
+ mystique->pixel_count++;
+ }
+
+ mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3];
+ mystique->dwgreg.dr[4] = r_back + mystique->dwgreg.dr[7];
+ mystique->dwgreg.dr[8] = g_back + mystique->dwgreg.dr[11];
+ mystique->dwgreg.dr[12] = b_back + mystique->dwgreg.dr[15];
+
+ while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0])
+ {
+ mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0];
+ mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1);
+ }
+ mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2];
+
+ while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6])
+ {
+ mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6];
+ mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1);
+ }
+ mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5];
+
+ dx = (int16_t)((mystique->dwgreg.fxleft - old_x_l) & 0xffff);
+ mystique->dwgreg.dr[0] += dx*mystique->dwgreg.dr[2];
+ mystique->dwgreg.dr[4] += dx*mystique->dwgreg.dr[6];
+ mystique->dwgreg.dr[8] += dx*mystique->dwgreg.dr[10];
+ mystique->dwgreg.dr[12] += dx*mystique->dwgreg.dr[14];
+
+ mystique->dwgreg.ydst++;
+ mystique->dwgreg.ydst &= 0x7fffff;
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK);
+
+ mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7;
+ }
+ break;
+
+ default:
+ fatal("Unknown atype %03x %08x TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+
+ mystique->blitter_complete_refcount++;
+}
+
+static int texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atransp)
+{
+ svga_t *svga = &mystique->svga;
+ const int tex_shift = 3 + ((mystique->dwgreg.texctl & TEXCTL_TPITCH_MASK) >> TEXCTL_TPITCH_SHIFT);
+ const unsigned int palsel = mystique->dwgreg.texctl & TEXCTL_PALSEL_MASK;
+ const uint16_t tckey = mystique->dwgreg.textrans & TEXTRANS_TCKEY_MASK;
+ const uint16_t tkmask = (mystique->dwgreg.textrans & TEXTRANS_TKMASK_MASK) >> TEXTRANS_TKMASK_SHIFT;
+ const unsigned int w_mask = (mystique->dwgreg.texwidth & TEXWIDTH_TWMASK_MASK) >> TEXWIDTH_TWMASK_SHIFT;
+ const unsigned int h_mask = (mystique->dwgreg.texheight & TEXHEIGHT_THMASK_MASK) >> TEXHEIGHT_THMASK_SHIFT;
+ uint16_t src = 0;
+ int s, t;
+
+ if (mystique->dwgreg.texctl & TEXCTL_NPCEN)
+ {
+ const int s_shift = 20 - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK);
+ const int t_shift = 20 - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK);
+
+ s = (int32_t)mystique->dwgreg.tmr[6] >> s_shift;
+ t = (int32_t)mystique->dwgreg.tmr[7] >> t_shift;
+ }
+ else
+ {
+ const int s_shift = (20 + 16) - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK);
+ const int t_shift = (20 + 16) - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK);
+ int64_t q = mystique->dwgreg.tmr[8] ? ((0x100000000ll / (int64_t)(int32_t)mystique->dwgreg.tmr[8]) /*>> 16*/) : 0;
+
+ s = (((int64_t)(int32_t)mystique->dwgreg.tmr[6] * q) /*<< 8*/) >> s_shift;/*((16+20)-12);*/
+ t = (((int64_t)(int32_t)mystique->dwgreg.tmr[7] * q) /*<< 8*/) >> t_shift;/*((16+20)-9);*/
+ }
+
+ if (mystique->dwgreg.texctl & TEXCTL_CLAMPU)
+ {
+ if (s < 0)
+ s = 0;
+ else if (s > w_mask)
+ s = w_mask;
+ }
+ else
+ s &= w_mask;
+
+ if (mystique->dwgreg.texctl & TEXCTL_CLAMPV)
+ {
+ if (t < 0)
+ t = 0;
+ else if (t > h_mask)
+ t = h_mask;
+ }
+ else
+ t &= h_mask;
+
+ switch (mystique->dwgreg.texctl & TEXCTL_TEXFORMAT_MASK)
+ {
+ case TEXCTL_TEXFORMAT_TW4:
+ src = svga->vram[(mystique->dwgreg.texorg + (((t << tex_shift) + s) >> 1)) & mystique->vram_mask];
+ if (s & 1)
+ src >>= 4;
+ else
+ src &= 0xf;
+ *tex_r = mystique->lut[src | palsel].r;
+ *tex_g = mystique->lut[src | palsel].g;
+ *tex_b = mystique->lut[src | palsel].b;
+ *atransp = 0;
+ break;
+ case TEXCTL_TEXFORMAT_TW8:
+ src = svga->vram[(mystique->dwgreg.texorg + (t << tex_shift) + s) & mystique->vram_mask];
+ *tex_r = mystique->lut[src].r;
+ *tex_g = mystique->lut[src].g;
+ *tex_b = mystique->lut[src].b;
+ *atransp = 0;
+ break;
+ case TEXCTL_TEXFORMAT_TW15:
+ src = ((uint16_t *)svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w];
+ *tex_r = ((src >> 10) & 0x1f) << 3;
+ *tex_g = ((src >> 5) & 0x1f) << 3;
+ *tex_b = (src & 0x1f) << 3;
+ if (((src >> 15) & mystique->dwgreg.ta_mask) == mystique->dwgreg.ta_key)
+ *atransp = 1;
+ else
+ *atransp = 0;
+ break;
+ case TEXCTL_TEXFORMAT_TW16:
+ src = ((uint16_t *)svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w];
+ *tex_r = (src >> 11) << 3;
+ *tex_g = ((src >> 5) & 0x3f) << 2;
+ *tex_b = (src & 0x1f) << 3;
+ *atransp = 0;
+ break;
+ default:
+ fatal("Unknown texture format %i\n", mystique->dwgreg.texctl & TEXCTL_TEXFORMAT_MASK);
+ break;
+ }
+
+ return ((src & tkmask) == tckey);
+}
+
+static void blit_texture_trap(mystique_t *mystique)
+{
+ svga_t *svga = &mystique->svga;
+ int y;
+ int z_write;
+ const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT;
+ const int dest32 = ((mystique->maccess_running & MACCESS_PWIDTH_MASK) == MACCESS_PWIDTH_32);
+
+ mystique->trap_count++;
+
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK)
+ {
+ case DWGCTRL_ATYPE_I:
+ case DWGCTRL_ATYPE_ZI:
+ z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI);
+// pclog("fxleft=%i fxright=%i texctl=%08x texorg=%08x ydst=%i len=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright, mystique->dwgreg.texctl, mystique->dwgreg.texorg, mystique->dwgreg.ydst, mystique->dwgreg.length);
+/* pclog("fcol=%08x\n", mystique->dwgreg.fcol);
+ pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length);
+ pclog("pitch=%08x\n", mystique->dwgreg.pitch);
+ pclog("ydst=%i ydst_lin=%08x\n", mystique->dwgreg.ydst, mystique->dwgreg.ydst_lin);
+ pclog("dYl =%08x errl =%08x -|dXl|=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[1], mystique->dwgreg.ar[2]);
+ pclog("errr=%08x -|dXr|=%08x dYr =%08x\n", mystique->dwgreg.ar[4], mystique->dwgreg.ar[5], mystique->dwgreg.ar[6]);
+ pclog(" q/wc=%08x q/wc/dX=%08x q/wc/dY=%08x\n",
+ mystique->dwgreg.tmr[8], mystique->dwgreg.tmr[4], mystique->dwgreg.tmr[5]);
+ pclog(" s/wc=%08x s/wc/dX=%08x s/wc/dY=%08x\n",
+ mystique->dwgreg.tmr[6], mystique->dwgreg.tmr[0], mystique->dwgreg.tmr[1]);
+ pclog(" t/wc=%08x t/wc/dX=%08x t/wc/dY=%08x\n",
+ mystique->dwgreg.tmr[7], mystique->dwgreg.tmr[2], mystique->dwgreg.tmr[3]);*/
+
+ for (y = 0; y < mystique->dwgreg.length; y++)
+ {
+ uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4];
+ uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask];
+ int16_t x_l = mystique->dwgreg.fxleft & 0xffff;
+ int16_t x_r = mystique->dwgreg.fxright & 0xffff;
+ int16_t old_x_l = x_l;
+ int dx;
+
+ uint32_t z_back = mystique->dwgreg.dr[0];
+ uint32_t r_back = mystique->dwgreg.dr[4];
+ uint32_t g_back = mystique->dwgreg.dr[8];
+ uint32_t b_back = mystique->dwgreg.dr[12];
+ uint32_t s_back = mystique->dwgreg.tmr[6];
+ uint32_t t_back = mystique->dwgreg.tmr[7];
+ uint32_t q_back = mystique->dwgreg.tmr[8];
+
+// pclog(" line %i: %i %i %08x %08x %08x %08x %i\n", __y, x_l, x_r, mystique->dwgreg.dr[0],mystique->dwgreg.dr[2],mystique->dwgreg.dr[3], mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg, z_write);
+// pclog(" %08x %08x %08x\n", mystique->dwgreg.tmr[4],mystique->dwgreg.tmr[5], mystique->dwgreg.tmr[8]);
+// pclog(" %08x %08x %08x\n", mystique->dwgreg.ar[4], mystique->dwgreg.ar[5], mystique->dwgreg.ar[6]);
+
+ while (x_l != x_r)
+ {
+ if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot &&
+ trans[x_l & 3])
+ {
+ uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15);
+ uint16_t old_z = z_p[x_l];
+
+ if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK))
+ {
+ int tex_r = 0, tex_g = 0, tex_b = 0;
+ int ctransp, atransp = 0;
+ int i_r = 0, i_g = 0, i_b = 0;
+
+ if (!(mystique->dwgreg.dr[4] & (1 << 23)))
+ i_r = (mystique->dwgreg.dr[4] >> 15) & 0xff;
+ if (!(mystique->dwgreg.dr[8] & (1 << 23)))
+ i_g = (mystique->dwgreg.dr[8] >> 15) & 0xff;
+ if (!(mystique->dwgreg.dr[12] & (1 << 23)))
+ i_b = (mystique->dwgreg.dr[12] >> 15) & 0xff;
+
+ ctransp = texture_read(mystique, &tex_r, &tex_g, &tex_b, &atransp);
+
+ switch (mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY))
+ {
+ case 0:
+ if (ctransp)
+ goto skip_pixel;
+ if (atransp)
+ {
+ tex_r = i_r;
+ tex_g = i_g;
+ tex_b = i_b;
+ }
+ break;
+
+ case TEXCTL_DECALCKEY:
+ if (ctransp)
+ {
+ tex_r = i_r;
+ tex_g = i_g;
+ tex_b = i_b;
+ }
+ break;
+
+ case (TEXCTL_STRANS | TEXCTL_DECALCKEY):
+ if (ctransp)
+ goto skip_pixel;
+ break;
+
+ case TEXCTL_TMODULATE:
+ if (ctransp)
+ goto skip_pixel;
+ if (mystique->dwgreg.texctl & TEXCTL_TMODULATE)
+ {
+ tex_r = (tex_r * i_r) >> 8;
+ tex_g = (tex_g * i_g) >> 8;
+ tex_b = (tex_b * i_b) >> 8;
+ }
+ break;
+
+ case (TEXCTL_TMODULATE | TEXCTL_STRANS):
+ if (ctransp || atransp)
+ goto skip_pixel;
+ if (mystique->dwgreg.texctl & TEXCTL_TMODULATE)
+ {
+ tex_r = (tex_r * i_r) >> 8;
+ tex_g = (tex_g * i_g) >> 8;
+ tex_b = (tex_b * i_b) >> 8;
+ }
+ break;
+
+
+ default:
+ fatal("Bad TEXCTL %08x %08x\n", mystique->dwgreg.texctl, mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY));
+ }
+
+ if (dest32)
+ {
+ ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = tex_b | (tex_g << 8) | (tex_r << 16);
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount;
+ }
+ else
+ {
+ ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dither(mystique, tex_r, tex_g, tex_b, x_l & 1, mystique->dwgreg.selline & 1);
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount;
+ }
+ if (z_write)
+ z_p[x_l] = z;
+ }
+ }
+skip_pixel:
+ x_l++;
+ mystique->pixel_count++;
+
+ mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2];
+ mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6];
+ mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10];
+ mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14];
+ mystique->dwgreg.tmr[6] += mystique->dwgreg.tmr[0];
+ mystique->dwgreg.tmr[7] += mystique->dwgreg.tmr[2];
+ mystique->dwgreg.tmr[8] += mystique->dwgreg.tmr[4];
+ }
+
+ mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3];
+ mystique->dwgreg.dr[4] = r_back + mystique->dwgreg.dr[7];
+ mystique->dwgreg.dr[8] = g_back + mystique->dwgreg.dr[11];
+ mystique->dwgreg.dr[12] = b_back + mystique->dwgreg.dr[15];
+ mystique->dwgreg.tmr[6] = s_back + mystique->dwgreg.tmr[1];
+ mystique->dwgreg.tmr[7] = t_back + mystique->dwgreg.tmr[3];
+ mystique->dwgreg.tmr[8] = q_back + mystique->dwgreg.tmr[5];
+
+ while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0])
+ {
+ mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0];
+ mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1);
+ }
+ mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2];
+
+ while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6])
+ {
+ mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6];
+ mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1);
+ }
+ mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5];
+
+ dx = (int16_t)((mystique->dwgreg.fxleft - old_x_l) & 0xffff);
+ mystique->dwgreg.dr[0] += dx*mystique->dwgreg.dr[2];
+ mystique->dwgreg.dr[4] += dx*mystique->dwgreg.dr[6];
+ mystique->dwgreg.dr[8] += dx*mystique->dwgreg.dr[10];
+ mystique->dwgreg.dr[12] += dx*mystique->dwgreg.dr[14];
+ mystique->dwgreg.tmr[6] += dx*mystique->dwgreg.tmr[0];
+ mystique->dwgreg.tmr[7] += dx*mystique->dwgreg.tmr[2];
+ mystique->dwgreg.tmr[8] += dx*mystique->dwgreg.tmr[4];
+
+ mystique->dwgreg.ydst++;
+ mystique->dwgreg.ydst &= 0x7fffff;
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK);
+
+ mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7;
+ }
+ break;
+
+ default:
+ fatal("Unknown atype %03x %08x TEXTURE_TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+
+ mystique->blitter_complete_refcount++;
+}
+
+static void blit_bitblt(mystique_t *mystique)
+{
+ svga_t *svga = &mystique->svga;
+ uint32_t src_addr;
+ int y;
+ int x_dir = mystique->dwgreg.sgn.scanleft ? -1 : 1;
+ int16_t x_start = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxright : mystique->dwgreg.fxleft;
+ int16_t x_end = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxleft : mystique->dwgreg.fxright;
+ const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT;
+
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK)
+ {
+ case DWGCTRL_ATYPE_BLK:
+// if (mystique->maccess_running & MACCESS_TLUTLOAD)
+// fatal("Bitblt TLUTLOAD BLK\n");
+// if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN)
+// fatal("BITBLT BLK with pattern\n");
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK)
+ {
+ case DWGCTRL_BLTMOD_BMONOLEF:
+// pclog("ar0=%08x ar3=%08x ar5=%08x dwgctrl=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[3], mystique->dwgreg.ar[5], mystique->dwgreg.dwgctrl_running);
+// pclog("fxleft=%i fxright=%i ydst=%i fcol=%08x bcol=%08x\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright, mystique->dwgreg.ydst, mystique->dwgreg.fcol, mystique->dwgreg.bcol);
+
+ src_addr = mystique->dwgreg.ar[3];
+// mystique->dwgreg.bit_offset = 0;
+
+ for (y = 0; y < mystique->dwgreg.length; y++)
+ {
+ int16_t x = x_start;
+
+// pclog(" line %03i: %08x %08x %02x\n", y, mystique->dwgreg.ydst_lin, src_addr, svga->vram[0x2eba3]);
+ while (1)
+ {
+ if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot)
+ {
+ uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask;
+ int bit_offset = src_addr & 7;
+ uint32_t old_dst;
+
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_8:
+// pclog(" pix %i %02x %i %i %06x\n", x, svga->vram[byte_addr], svga->vram[byte_addr] & (1 << bit_offset), mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC, byte_addr);
+ if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)
+ {
+ if (svga->vram[byte_addr] & (1 << bit_offset))
+ svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = mystique->dwgreg.fcol;
+ }
+ else
+ svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] =
+ (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_16:
+// pclog(" pix %i %02x %i %i %06x\n", x, svga->vram[byte_addr], svga->vram[byte_addr] & (1 << bit_offset), mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC, byte_addr);
+ if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)
+ {
+ if (svga->vram[byte_addr] & (1 << bit_offset))
+ ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = mystique->dwgreg.fcol;
+ }
+ else
+ ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] =
+ (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_24:
+ old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask];
+// pclog(" pix %i %02x %i %i %06x\n", x, svga->vram[byte_addr], svga->vram[byte_addr] & (1 << bit_offset), mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC, byte_addr);
+ if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)
+ {
+ if (svga->vram[byte_addr] & (1 << bit_offset))
+ *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] =
+ (old_dst & 0xff000000) | (mystique->dwgreg.fcol & 0xffffff);
+ }
+ else
+ *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] =
+ (old_dst & 0xff000000) | (((svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffffff);
+ svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_32:
+// pclog(" pix %i %02x %i %i %06x\n", x, svga->vram[byte_addr], svga->vram[byte_addr] & (1 << bit_offset), mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC, byte_addr);
+ if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)
+ {
+ if (svga->vram[byte_addr] & (1 << bit_offset))
+ ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & 0xfffff] = mystique->dwgreg.fcol;
+ }
+ else
+ ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & 0xfffff] =
+ (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount;
+ break;
+
+ default:
+ fatal("BITBLT DWGCTRL_ATYPE_BLK unknown MACCESS %i\n", mystique->maccess_running & MACCESS_PWIDTH_MASK);
+ }
+ }
+
+ if (src_addr == mystique->dwgreg.ar[0])
+ {
+ mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5];
+ mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5];
+ src_addr = mystique->dwgreg.ar[3];
+ }
+ else
+ src_addr += x_dir;
+
+ if (x != x_end)
+ x += x_dir;
+ else
+ break;
+ }
+
+ if (mystique->dwgreg.sgn.sdy)
+ mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK);
+ else
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK);
+ }
+ break;
+
+ default:
+ fatal("BITBLT BLK %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK);
+ break;
+ }
+ break;
+
+
+ case DWGCTRL_ATYPE_RPL:
+// pclog(" bitblt RPL\n");
+ if (mystique->maccess_running & MACCESS_TLUTLOAD)
+ {
+// pclog("TLUTLOAD!\n");
+ src_addr = mystique->dwgreg.ar[3];
+
+ y = mystique->dwgreg.ydst;
+
+ while (mystique->dwgreg.length)
+ {
+ uint16_t src = ((uint16_t *)svga->vram)[src_addr & mystique->vram_mask_w];
+// pclog(" LUT[%02x]=VRAM[%05X]=%04x\n", y & 0xff, src_addr, src);
+
+ mystique->lut[y & 0xff].r = (src >> 11) << 3;
+ mystique->lut[y & 0xff].g = ((src >> 5) & 0x3f) << 2;
+ mystique->lut[y & 0xff].b = (src & 0x1f) << 3;
+ src_addr++;
+ y++;
+ mystique->dwgreg.length--;
+ }
+ break;
+ }
+ case DWGCTRL_ATYPE_RSTR:
+// pclog(" bitblt RPL or RSTR\n");
+// if (mystique->maccess_running & MACCESS_TLUTLOAD)
+// fatal("Bitblt TLUTLOAD RSTR\n");
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK)
+ {
+ case DWGCTRL_BLTMOD_BMONOLEF:
+// pclog("ar0=%08x ar3=%08x ar5=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[3], mystique->dwgreg.ar[5]);
+// pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright);
+
+ if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN)
+ fatal("BITBLT RPL/RSTR BMONOLEF with pattern\n");
+
+ src_addr = mystique->dwgreg.ar[3];
+
+ for (y = 0; y < mystique->dwgreg.length; y++)
+ {
+ uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4];
+ int16_t x = x_start;
+
+// pclog(" line %03i: %08x %08x\n", y, mystique->dwgreg.ydst_lin, src_addr);
+ while (1)
+ {
+ uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask;
+ int bit_offset = src_addr & 7;
+
+ if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot &&
+ ((svga->vram[byte_addr] & (1 << bit_offset)) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) &&
+ trans[x & 3])
+ {
+ uint32_t src = (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol;
+ uint32_t dst, old_dst;
+
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_8:
+ dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask];
+
+// pclog(" %02x %02x ", src, dst);
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK
+// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst);
+
+ svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_16:
+ dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w];
+
+// pclog(" %02x %02x ", src, dst);
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK
+// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst);
+
+ ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_24:
+ old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask];
+
+// pclog(" %02x %02x ", src, old_dst);
+ dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK
+// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst);
+
+ *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000);
+ svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_32:
+ dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l];
+
+// pclog(" %02x %02x ", src, dst);
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK
+// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst);
+
+ ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 10] = changeframecount;
+ break;
+
+ default:
+ fatal("BITBLT RPL BMONOLEF PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+ }
+
+ if (src_addr == mystique->dwgreg.ar[0])
+ {
+ mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5];
+ mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5];
+ src_addr = mystique->dwgreg.ar[3];
+ }
+ else
+ src_addr += x_dir;
+
+ if (x != x_end)
+ x += x_dir;
+ else
+ break;
+ }
+
+ if (mystique->dwgreg.sgn.sdy)
+ mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK);
+ else
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK);
+ }
+ break;
+
+
+ case DWGCTRL_BLTMOD_BFCOL:
+ case DWGCTRL_BLTMOD_BU32RGB:
+// pclog("ar0=%08x ar3=%08x ar5=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[3], mystique->dwgreg.ar[5]);
+// pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright);
+
+ src_addr = mystique->dwgreg.ar[3];
+
+ for (y = 0; y < mystique->dwgreg.length; y++)
+ {
+ uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4];
+ uint32_t old_src_addr = src_addr;
+ int16_t x = x_start;
+
+// pclog(" line %03i: %08x %08x\n", y, mystique->dwgreg.ydst_lin, src_addr);
+ while (1)
+ {
+ if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright &&
+ mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot &&
+ trans[x & 3])
+ {
+ uint32_t src, dst, old_dst;
+
+ switch (mystique->maccess_running & MACCESS_PWIDTH_MASK)
+ {
+ case MACCESS_PWIDTH_8:
+ src = svga->vram[src_addr & mystique->vram_mask];
+ dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask];
+
+// pclog(" %02x %02x ", src, dst);
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK
+// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst);
+
+ svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_16:
+ src = ((uint16_t *)svga->vram)[src_addr & mystique->vram_mask_w];
+ dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w];
+
+// pclog(" %02x %02x ", src, dst);
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK
+// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst);
+
+ ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_24:
+ src = *(uint32_t *)&svga->vram[(src_addr * 3) & mystique->vram_mask];
+ old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask];
+
+// pclog(" %02x %02x ", src, old_dst);
+ dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK
+// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst);
+
+ *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000);
+ svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount;
+ break;
+
+ case MACCESS_PWIDTH_32:
+ src = ((uint32_t *)svga->vram)[src_addr & mystique->vram_mask_l];
+ dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l];
+
+// pclog(" %02x %02x ", src, dst);
+ dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK
+// pclog("%08x %08x %i dst=%02x\n", src_addr, mystique->dwgreg.ydst_lin + x, mystique->dwgreg.sgn.scanleft, dst);
+
+ ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst;
+ svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount;
+ break;
+
+ default:
+ fatal("BITBLT RPL BFCOL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+ }
+
+ if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN)
+ src_addr = ((src_addr + x_dir) & 7) | (src_addr & ~7);
+ else if (src_addr == mystique->dwgreg.ar[0])
+ {
+ mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5];
+ mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5];
+ src_addr = mystique->dwgreg.ar[3];
+ }
+ else
+ src_addr += x_dir;
+
+ if (x != x_end)
+ x += x_dir;
+ else
+ break;
+ }
+
+ if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN)
+ {
+ src_addr = old_src_addr;
+ if (mystique->dwgreg.sgn.sdy)
+ src_addr = ((src_addr - 32) & 0xe0) | (src_addr & ~0xe0);
+ else
+ src_addr = ((src_addr + 32) & 0xe0) | (src_addr & ~0xe0);
+ }
+
+ if (mystique->dwgreg.sgn.sdy)
+ mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK);
+ else
+ mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK);
+ }
+ break;
+
+ default:
+ fatal("BITBLT DWGCTRL_ATYPE_RPL unknown BLTMOD %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+ break;
+
+ default:
+ fatal("Unknown BITBLT atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+ mystique->blitter_complete_refcount++;
+}
+
+static void blit_iload(mystique_t *mystique)
+{
+// if (mystique->maccess_running & MACCESS_TLUTLOAD)
+// fatal("ILOAD TLUTLOAD\n");
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK)
+ {
+ case DWGCTRL_ATYPE_RPL:
+ case DWGCTRL_ATYPE_RSTR:
+ case DWGCTRL_ATYPE_BLK:
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK)
+ {
+ case DWGCTRL_BLTMOD_BFCOL:
+ case DWGCTRL_BLTMOD_BMONOLEF:
+ case DWGCTRL_BLTMOD_BMONOWF:
+ case DWGCTRL_BLTMOD_BU24RGB:
+// pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright);
+// pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length);
+ mystique->dwgreg.length_cur = mystique->dwgreg.length;
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.iload_rem_data = 0;
+ mystique->dwgreg.iload_rem_count = 0;
+ mystique->busy = 1;
+ mystique->dwgreg.words = 0;
+ break;
+
+ default:
+ fatal("ILOAD DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running);
+ break;
+ }
+ break;
+
+ default:
+ fatal("Unknown ILOAD atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+}
+
+static void blit_idump(mystique_t *mystique)
+{
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK)
+ {
+ case DWGCTRL_ATYPE_RPL:
+// pclog("ar0=%08x ar3=%08x ar5=%08x\n", mystique->dwgreg.ar[0], mystique->dwgreg.ar[3], mystique->dwgreg.ar[5]);
+// pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright);
+ mystique->dwgreg.length_cur = mystique->dwgreg.length;
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.src_addr = mystique->dwgreg.ar[3];
+ mystique->dwgreg.words = 0;
+ mystique->dwgreg.iload_rem_count = 0;
+ mystique->dwgreg.iload_rem_data = 0;
+ mystique->dwgreg.idump_end_of_line = 0;
+ mystique->busy = 1;
+ break;
+
+ default:
+ fatal("Unknown IDUMP atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+}
+
+static void blit_iload_scale(mystique_t *mystique)
+{
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK)
+ {
+ case DWGCTRL_ATYPE_RPL:
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK)
+ {
+ case DWGCTRL_BLTMOD_BUYUV:
+/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright);
+ pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length);
+ pclog("ar0=%08x\n", mystique->dwgreg.ar[0]);
+ pclog("ar2=%08x\n", mystique->dwgreg.ar[2]);
+ pclog("ar3=%08x\n", mystique->dwgreg.ar[3]);
+ pclog("ar5=%08x\n", mystique->dwgreg.ar[5]);
+ pclog("ar6=%08x\n", mystique->dwgreg.ar[6]);*/
+ mystique->dwgreg.length_cur = mystique->dwgreg.length;
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.iload_rem_data = 0;
+ mystique->dwgreg.iload_rem_count = 0;
+ mystique->busy = 1;
+ mystique->dwgreg.words = 0;
+ break;
+
+ default:
+ fatal("ILOAD_SCALE DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running);
+ break;
+ }
+ break;
+
+ default:
+ fatal("Unknown ILOAD_SCALE atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+}
+static void blit_iload_high(mystique_t *mystique)
+{
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK)
+ {
+ case DWGCTRL_ATYPE_RPL:
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK)
+ {
+ case DWGCTRL_BLTMOD_BUYUV:
+/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright);
+ pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length);
+ pclog("ar0=%08x\n", mystique->dwgreg.ar[0]);
+ pclog("ar2=%08x\n", mystique->dwgreg.ar[2]);
+ pclog("ar3=%08x\n", mystique->dwgreg.ar[3]);
+ pclog("ar5=%08x\n", mystique->dwgreg.ar[5]);
+ pclog("ar6=%08x\n", mystique->dwgreg.ar[6]);*/
+ mystique->dwgreg.length_cur = mystique->dwgreg.length;
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.iload_rem_data = 0;
+ mystique->dwgreg.iload_rem_count = 0;
+ mystique->busy = 1;
+ mystique->dwgreg.words = 0;
+ break;
+
+ default:
+ fatal("ILOAD_HIGH DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running);
+ break;
+ }
+ break;
+
+ default:
+ fatal("Unknown ILOAD_HIGH atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+}
+static void blit_iload_highv(mystique_t *mystique)
+{
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK)
+ {
+ case DWGCTRL_ATYPE_RPL:
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK)
+ {
+ case DWGCTRL_BLTMOD_BUYUV:
+/* pclog("fxleft=%i fxright=%i\n", mystique->dwgreg.fxleft, mystique->dwgreg.fxright);
+ pclog("ytop=%i length=%i\n", mystique->dwgreg.ytop, mystique->dwgreg.length);
+ pclog("ar0=%08x\n", mystique->dwgreg.ar[0]);
+ pclog("ar2=%08x\n", mystique->dwgreg.ar[2]);
+ pclog("ar3=%08x\n", mystique->dwgreg.ar[3]);
+ pclog("ar5=%08x\n", mystique->dwgreg.ar[5]);
+ pclog("ar6=%08x\n", mystique->dwgreg.ar[6]);*/
+ mystique->dwgreg.length_cur = mystique->dwgreg.length;
+ mystique->dwgreg.xdst = mystique->dwgreg.fxleft;
+ mystique->dwgreg.iload_rem_data = 0;
+ mystique->dwgreg.iload_rem_count = 0;
+ mystique->busy = 1;
+ mystique->dwgreg.words = 0;
+ mystique->dwgreg.highv_line = 0;
+ mystique->dwgreg.lastpix_r = 0;
+ mystique->dwgreg.lastpix_g = 0;
+ mystique->dwgreg.lastpix_b = 0;
+ break;
+
+ default:
+ fatal("ILOAD_HIGHV DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running);
+ break;
+ }
+ break;
+
+ default:
+ fatal("Unknown ILOAD_HIGHV atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running);
+ }
+}
+
+static void mystique_start_blit(mystique_t *mystique)
+{
+ uint64_t start_time = timer_read();
+ uint64_t end_time;
+
+ mystique->dwgreg.dwgctrl_running = mystique->dwgreg.dwgctrl;
+ mystique->maccess_running = mystique->maccess;
+// pclog("start_blit %08x length=%i fxleft=%i fxright=%i %02x %i %i %i ylin=%08x ytop=%08x ybot=%08x\n", mystique->dwgreg.dwgctrl_running, mystique->dwgreg.length, mystique->dwgreg.fxleft, mystique->dwgreg.fxright, mystique->svga.vram[0x5c056], mystique->blitter_submit_refcount, mystique->blitter_submit_dma_refcount, mystique->blitter_complete_refcount, mystique->dwgreg.ydst_lin, mystique->dwgreg.ytop, mystique->dwgreg.ybot);
+ if (mystique->busy)
+ fatal("mystique_start_blit: mystique->busy!\n");
+ if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SOLID)
+ {
+ int x, y;
+
+ for (y = 0; y < 8; y++)
+ {
+ for (x = 0; x < 8; x++)
+ mystique->dwgreg.pattern[y][x] = 1;
+ }
+ mystique->dwgreg.src[0] = 0xffffffff;
+ mystique->dwgreg.src[1] = 0xffffffff;
+ mystique->dwgreg.src[2] = 0xffffffff;
+ mystique->dwgreg.src[3] = 0xffffffff;
+ }
+ if (mystique->dwgreg.dwgctrl_running & DWGCTRL_ARZERO)
+ {
+ mystique->dwgreg.ar[0] = 0;
+ mystique->dwgreg.ar[1] = 0;
+ mystique->dwgreg.ar[2] = 0;
+ mystique->dwgreg.ar[4] = 0;
+ mystique->dwgreg.ar[5] = 0;
+ mystique->dwgreg.ar[6] = 0;
+ }
+ if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SGNZERO)
+ {
+ mystique->dwgreg.sgn.sdydxl = 0;
+ mystique->dwgreg.sgn.scanleft = 0;
+ mystique->dwgreg.sgn.sdxl = 0;
+ mystique->dwgreg.sgn.sdy = 0;
+ mystique->dwgreg.sgn.sdxr = 0;
+ }
+ if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SHTZERO)
+ {
+ mystique->dwgreg.funcnt = 0;
+ mystique->dwgreg.stylelen = 0;
+ mystique->dwgreg.xoff = 0;
+ mystique->dwgreg.yoff = 0;
+ }
+
+ switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK)
+ {
+ case DWGCTRL_OPCODE_LINE_OPEN:
+ blit_line(mystique, 0);
+ break;
+
+ case DWGCTRL_OPCODE_AUTOLINE_OPEN:
+ blit_autoline(mystique, 0);
+ break;
+
+ case DWGCTRL_OPCODE_AUTOLINE_CLOSE:
+ blit_autoline(mystique, 1);
+ break;
+
+ case DWGCTRL_OPCODE_TRAP:
+ blit_trap(mystique);
+ break;
+
+ case DWGCTRL_OPCODE_TEXTURE_TRAP:
+ blit_texture_trap(mystique);
+ break;
+
+ case DWGCTRL_OPCODE_ILOAD_HIGH:
+ blit_iload_high(mystique);
+ break;
+
+ case DWGCTRL_OPCODE_BITBLT:
+ blit_bitblt(mystique);
+ break;
+
+ case DWGCTRL_OPCODE_ILOAD:
+ blit_iload(mystique);
+ break;
+
+ case DWGCTRL_OPCODE_IDUMP:
+ blit_idump(mystique);
+ break;
+
+ case DWGCTRL_OPCODE_ILOAD_SCALE:
+ blit_iload_scale(mystique);
+ break;
+
+ case DWGCTRL_OPCODE_ILOAD_HIGHV:
+ blit_iload_highv(mystique);
+ break;
+
+ default:
+ fatal("mystique_start_blit: unknown blit %08x\n", mystique->dwgreg.dwgctrl_running);
+ }
+// pclog("blit done\n");
+
+ end_time = timer_read();
+ mystique->blitter_time += end_time - start_time;
+}
+
+
+static void mystique_hwcursor_draw(svga_t *svga, int displine)
+{
+ mystique_t *mystique = (mystique_t *)svga->p;
+ int x;
+ uint64_t dat[2];
+ int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
+
+ dat[0] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr]);
+ dat[1] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr + 8]);
+ svga->hwcursor_latch.addr += 16;
+ switch (mystique->xcurctrl & XCURCTRL_CURMODE_MASK)
+ {
+ case XCURCTRL_CURMODE_XGA:
+ for (x = 0; x < 64; x ++)
+ {
+ if (!(dat[1] & (1ull << 63)))
+ ((uint32_t *)buffer32->line[displine])[offset + 32] = (dat[0] & (1ull << 63)) ? mystique->cursor.col[1] : mystique->cursor.col[0];
+ else if (dat[0] & (1ull << 63))
+ ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff;
+
+ offset++;
+ dat[0] <<= 1;
+ dat[1] <<= 1;
+ }
+ break;
+ }
+}
+
+
+
+
+static uint8_t mystique_pci_read(int func, int addr, void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+
+// pclog("mystique PCI read %08X\n", addr);
+ switch (addr)
+ {
+ case 0x00: return 0x2b; /*Matrox*/
+ case 0x01: return 0x10;
+
+ case 0x02: return 0x1a; /*MGA-1064SG*/
+ case 0x03: return 0x05;
+
+ case PCI_REG_COMMAND:
+ return mystique->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/
+
+ case 0x07: return 0 << 1; /*Fast DEVSEL timing*/
+
+ case 0x08: return 0; /*Revision ID*/
+ case 0x09: return 0; /*Programming interface*/
+
+ case 0x0a: return 0x00; /*Supports VGA interface*/
+ case 0x0b: return 0x03;
+
+ case 0x10: return 0x00; /*Control aperture*/
+ case 0x11: return (mystique->ctrl_base >> 8) & 0xc0;
+ case 0x12: return mystique->ctrl_base >> 16;
+ case 0x13: return mystique->ctrl_base >> 24;
+
+ case 0x14: return 0x00; /*Linear frame buffer*/
+ case 0x16: return (mystique->lfb_base >> 16) & 0x80;
+ case 0x17: return mystique->lfb_base >> 24;
+
+ case 0x18: return 0x00; /*Pseudo-DMA (ILOAD)*/
+ case 0x1a: return (mystique->iload_base >> 16) & 0x80;
+ case 0x1b: return mystique->iload_base >> 24;
+
+ case 0x30: return mystique->pci_regs[0x30] & 0x01; /*BIOS ROM address*/
+ case 0x31: return 0x00;
+ case 0x32: return mystique->pci_regs[0x32];
+ case 0x33: return mystique->pci_regs[0x33];
+
+ case 0x3c: return mystique->int_line;
+ case 0x3d: return PCI_INTA;
+
+ case 0x40: return mystique->pci_regs[0x40];
+ case 0x41: return mystique->pci_regs[0x41];
+ case 0x42: return mystique->pci_regs[0x42];
+ case 0x43: return mystique->pci_regs[0x43];
+
+ case 0x44: return mystique->pci_regs[0x44];
+ case 0x45: return mystique->pci_regs[0x45];
+
+ case 0x48: case 0x49: case 0x4a: case 0x4b:
+ addr = (mystique->pci_regs[0x44] & 0xfc) |
+ ((mystique->pci_regs[0x45] & 0x3f) << 8) |
+ (addr & 3);
+ return mystique_ctrl_read_b(addr, mystique);
+ }
+ return 0;
+}
+
+static void mystique_pci_write(int func, int addr, uint8_t val, void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+
+// pclog("mystique_pci_write: func=%i addr=%02x val=%02x\n", func, addr, val);
+ switch (addr)
+ {
+ case PCI_REG_COMMAND:
+ mystique->pci_regs[PCI_REG_COMMAND] = val & 0x23;
+ mystique_recalc_mapping(mystique);
+ break;
+
+ case 0x11:
+ mystique->ctrl_base = (mystique->ctrl_base & 0xffff0000) | ((val & 0xc0) << 8);
+ mystique_recalc_mapping(mystique);
+ break;
+ case 0x12:
+ mystique->ctrl_base = (mystique->ctrl_base & 0xff00c000) | (val << 16);
+ mystique_recalc_mapping(mystique);
+ break;
+ case 0x13:
+ mystique->ctrl_base = (mystique->ctrl_base & 0x00ffc000) | (val << 24);
+ mystique_recalc_mapping(mystique);
+ break;
+
+ case 0x16:
+ mystique->lfb_base = (mystique->lfb_base & 0xff000000) | ((val & 0x80) << 16);
+ mystique_recalc_mapping(mystique);
+ break;
+ case 0x17:
+ mystique->lfb_base = (mystique->lfb_base & 0x00800000) | (val << 24);
+ mystique_recalc_mapping(mystique);
+ break;
+
+ case 0x1a:
+ mystique->iload_base = (mystique->iload_base & 0xff000000) | ((val & 0x80) << 16);
+ mystique_recalc_mapping(mystique);
+ break;
+ case 0x1b:
+ mystique->iload_base = (mystique->iload_base & 0x00800000) | (val << 24);
+ mystique_recalc_mapping(mystique);
+ break;
+
+ case 0x30: case 0x32: case 0x33:
+ mystique->pci_regs[addr] = val;
+ if (mystique->pci_regs[0x30] & 0x01)
+ {
+ uint32_t addr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24);
+ mem_mapping_set_addr(&mystique->bios_rom.mapping, addr, 0x8000);
+ }
+ else
+ mem_mapping_disable(&mystique->bios_rom.mapping);
+ return;
+
+ case 0x3c:
+ mystique->int_line = val;
+ return;
+
+ case 0x40: case 0x41: case 0x42: case 0x43:
+ mystique->pci_regs[addr] = val;
+ break;
+
+ case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ mystique->pci_regs[addr-0x20] = val;
+ break;
+
+ case 0x44: case 0x45:
+ mystique->pci_regs[addr] = val;
+ break;
+
+ case 0x48: case 0x49: case 0x4a: case 0x4b:
+ addr = (mystique->pci_regs[0x44] & 0xfc) |
+ ((mystique->pci_regs[0x45] & 0x3f) << 8) |
+ (addr & 3);
+ mystique_ctrl_write_b(addr, val, mystique);
+ break;
+ }
+}
+
+void *mystique_init()
+{
+ int c;
+ mystique_t *mystique = malloc(sizeof(mystique_t));
+ memset(mystique, 0, sizeof(mystique_t));
+
+ rom_init(&mystique->bios_rom, "MYSTIQUE.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
+
+ mystique->vram_size = device_get_config_int("memory");
+ mystique->vram_mask = (mystique->vram_size << 20) - 1;
+ mystique->vram_mask_w = mystique->vram_mask >> 1;
+ mystique->vram_mask_l = mystique->vram_mask >> 2;
+
+ svga_init(&mystique->svga, mystique, mystique->vram_size << 20,
+ mystique_recalctimings,
+ mystique_in, mystique_out,
+ mystique_hwcursor_draw,
+ NULL);
+
+ io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique);
+ mem_mapping_add(&mystique->ctrl_mapping, 0, 0,
+ mystique_ctrl_read_b, NULL, mystique_ctrl_read_l,
+ mystique_ctrl_write_b, NULL, mystique_ctrl_write_l,
+ NULL, 0, mystique);
+ mem_mapping_add(&mystique->lfb_mapping, 0, 0,
+ svga_read_linear, svga_readw_linear, svga_readl_linear,
+ svga_write_linear, svga_writew_linear, svga_writel_linear,
+ NULL, 0, mystique);
+ mem_mapping_add(&mystique->iload_mapping, 0, 0,
+ mystique_iload_read_b, NULL, mystique_iload_read_l,
+ mystique_iload_write_b, NULL, mystique_iload_write_l,
+ NULL, 0, mystique);
+
+
+ mystique->card = pci_add(mystique_pci_read, mystique_pci_write, mystique);
+ mystique->pci_regs[0x2c] = mystique->bios_rom.rom[0x7ff8];
+ mystique->pci_regs[0x2d] = mystique->bios_rom.rom[0x7ff8];
+ mystique->pci_regs[0x2e] = mystique->bios_rom.rom[0x7ff8];
+ mystique->pci_regs[0x2f] = mystique->bios_rom.rom[0x7ff8];
+
+ mystique->svga.miscout = 1;
+ mystique->pci_regs[0x41] = 0x01; /*vgaboot=1*/
+
+// timer_add(&mystique->dma.timer, dma_callback, mystique, 1);
+
+ for (c = 0; c < 256; c++)
+ {
+ dither5[c][0][0] = c >> 3;
+ dither5[c][1][1] = (c + 2) >> 3;
+ dither5[c][1][0] = (c + 4) >> 3;
+ dither5[c][0][1] = (c + 6) >> 3;
+
+ if (dither5[c][1][1] > 31)
+ dither5[c][1][1] = 31;
+ if (dither5[c][1][0] > 31)
+ dither5[c][1][0] = 31;
+ if (dither5[c][0][1] > 31)
+ dither5[c][0][1] = 31;
+
+ dither6[c][0][0] = c >> 2;
+ dither6[c][1][1] = (c + 1) >> 2;
+ dither6[c][1][0] = (c + 2) >> 2;
+ dither6[c][0][1] = (c + 3) >> 2;
+
+ if (dither6[c][1][1] > 63)
+ dither6[c][1][1] = 63;
+ if (dither6[c][1][0] > 63)
+ dither6[c][1][0] = 63;
+ if (dither6[c][0][1] > 63)
+ dither6[c][0][1] = 63;
+ }
+
+ mystique->wake_fifo_thread = thread_create_event();
+ mystique->fifo_not_full_event = thread_create_event();
+ mystique->fifo_thread = thread_create(fifo_thread, mystique);
+ mystique->dma.lock = thread_create_mutex();
+
+ timer_add(&mystique->wake_timer, mystique_wake_timer, (void *)mystique, 0);
+ timer_add(&mystique->softrap_pending_timer, mystique_softrap_pending_timer, (void *)mystique, 1);
+
+ mystique->status = STATUS_ENDPRDMASTS;
+
+ mystique->svga.vsync_callback = mystique_vsync_callback;
+
+ return mystique;
+}
+
+static int mystique_available()
+{
+ return rom_present("MYSTIQUE.VBI");
+}
+
+static void mystique_close(void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+
+ thread_kill(mystique->fifo_thread);
+ thread_destroy_event(mystique->wake_fifo_thread);
+ thread_destroy_event(mystique->fifo_not_full_event);
+ thread_destroy_mutex(mystique->dma.lock);
+
+ svga_close(&mystique->svga);
+
+ free(mystique);
+}
+
+static void mystique_speed_changed(void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+
+ svga_recalctimings(&mystique->svga);
+}
+
+static void mystique_force_redraw(void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+
+ mystique->svga.fullchange = changeframecount;
+}
+
+static void mystique_add_status_info(char *s, int max_len, void *p)
+{
+ mystique_t *mystique = (mystique_t *)p;
+ char temps[256];
+ uint64_t new_time = timer_read();
+ uint64_t status_diff = new_time - mystique->status_time;
+ mystique->status_time = new_time;
+
+ if (!status_diff)
+ status_diff = 1;
+
+ svga_add_status_info(s, max_len, &mystique->svga);
+ sprintf(temps, "In %s mode\n%f Mpixels/sec\n%f ktraps/sec\n%f%% CPU\n%f%% CPU (real)\n\n",
+ (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE) ? "MGA" : "SVGA",
+ (double)mystique->pixel_count/1000000.0,
+ (double)mystique->trap_count/1000.0,
+ ((double)mystique->blitter_time * 100.0) / timer_freq,
+ ((double)mystique->blitter_time * 100.0) / status_diff);
+ strncat(s, temps, max_len);
+
+ mystique->pixel_count = mystique->trap_count = 0;
+ mystique->blitter_time = 0;
+}
+
+static device_config_t mystique_config[] =
+{
+ {
+ .name = "memory",
+ .description = "Memory size",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "2 MB",
+ .value = 2
+ },
+ {
+ .description = "4 MB",
+ .value = 4
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 4
+ },
+ {
+ .type = -1
+ }
+};
+
+device_t mystique_device =
+{
+ "Matrox Mystique",
+ DEVICE_NOT_WORKING,
+ mystique_init,
+ mystique_close,
+ mystique_available,
+ mystique_speed_changed,
+ mystique_force_redraw,
+ mystique_add_status_info,
+ mystique_config
+};
diff --git a/src/vid_mga.h b/src/vid_mga.h
new file mode 100644
index 0000000..278f7be
--- /dev/null
+++ b/src/vid_mga.h
@@ -0,0 +1 @@
+extern device_t mystique_device;
diff --git a/src/vid_oti067.c b/src/vid_oti067.c
index 1b7c20d..8494e6d 100644
--- a/src/vid_oti067.c
+++ b/src/vid_oti067.c
@@ -20,6 +20,7 @@ typedef struct oti067_t
uint8_t regs[32];
uint8_t pos;
+ uint8_t dipswitch_val;
uint32_t vram_size;
uint32_t vram_mask;
@@ -111,7 +112,7 @@ uint8_t oti067_in(uint16_t addr, void *p)
temp = oti067->index | (2 << 5);
break;
case 0x3DF:
- if (oti067->index==0x10) temp = 0x18;
+ if (oti067->index==0x10) temp = oti067->dipswitch_val;
else temp = oti067->regs[oti067->index];
break;
@@ -174,6 +175,8 @@ void *oti067_common_init(char *bios_fn, int vram_size)
io_sethandler(0x46e8, 0x0001, oti067_pos_in, NULL, NULL, oti067_pos_out, NULL, NULL, oti067);
oti067->svga.miscout = 1;
+
+ oti067->dipswitch_val = 0x18;
return oti067;
}
@@ -209,6 +212,14 @@ void *oti067_acer386_init()
return oti067;
}
+void *oti067_ama932j_init()
+{
+ oti067_t *oti067 = oti067_common_init("ama932j/oti067.bin", 512);
+
+ oti067->dipswitch_val |= 0x20;
+ return oti067;
+}
+
static int oti067_available()
{
return rom_present("oti067/bios.bin");
@@ -294,3 +305,14 @@ device_t oti067_acer386_device =
oti067_force_redraw,
oti067_add_status_info
};
+device_t oti067_ama932j_device =
+{
+ "Oak OTI-067 (AMA-932J)",
+ 0,
+ oti067_ama932j_init,
+ oti067_close,
+ oti067_available,
+ oti067_speed_changed,
+ oti067_force_redraw,
+ oti067_add_status_info
+};
diff --git a/src/vid_oti067.h b/src/vid_oti067.h
index cf1fa1b..8376b38 100644
--- a/src/vid_oti067.h
+++ b/src/vid_oti067.h
@@ -1,4 +1,5 @@
extern device_t oti067_device;
extern device_t oti067_acer386_device;
+extern device_t oti067_ama932j_device;
void oti067_enable_disable(void *p, int enable);
diff --git a/src/vid_paradise.c b/src/vid_paradise.c
index 3aabd3a..369fb34 100644
--- a/src/vid_paradise.c
+++ b/src/vid_paradise.c
@@ -101,9 +101,9 @@ void paradise_out(uint16_t addr, uint8_t val, void *p)
paradise_remap(paradise);
return;
}
- if (svga->gdcaddr == 0xe)
+ if (svga->gdcaddr == 0xb)
{
- svga->gdcreg[0xe] = val;
+ svga->gdcreg[0xb] = val;
paradise_remap(paradise);
return;
}
@@ -211,11 +211,11 @@ void paradise_remap(paradise_t *paradise)
paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0xa] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
}
- else if (svga->gdcreg[0xe] & 0x08)
+ else if (svga->gdcreg[0xb] & 0x08)
{
if (svga->gdcreg[0x6] & 0xc)
{
-// pclog("Remap 2\n");
+// pclog("Remap 2\n");
paradise->read_bank[0] = paradise->read_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0xa] & 0x7f) << 12;
paradise->read_bank[1] = paradise->read_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
@@ -238,7 +238,10 @@ void paradise_remap(paradise_t *paradise)
paradise->write_bank[0] = paradise->write_bank[2] = (svga->gdcreg[0x9] & 0x7f) << 12;
paradise->write_bank[1] = paradise->write_bank[3] = ((svga->gdcreg[0x9] & 0x7f) << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000);
}
-// pclog("Remap - %04X %04X\n", paradise->read_bank[0], paradise->write_bank[0]);
+ paradise->read_bank[1] &= 0x7ffff;
+ paradise->write_bank[1] &= 0x7ffff;
+
+// pclog("Remap - %04X %04X %04x %04x\n", paradise->read_bank[0], paradise->write_bank[0], paradise->read_bank[1], paradise->write_bank[1]);
}
void paradise_recalctimings(svga_t *svga)
diff --git a/src/vid_pc1512.c b/src/vid_pc1512.c
index 4c94a5a..35ffa20 100644
--- a/src/vid_pc1512.c
+++ b/src/vid_pc1512.c
@@ -26,6 +26,7 @@ typedef struct pc1512_t
uint8_t plane_write, plane_read, border;
+ int fontbase;
int linepos, displine;
int sc, vc;
int cgadispon;
@@ -57,10 +58,10 @@ static void pc1512_out(uint16_t addr, uint8_t val, void *p)
// pclog("PC1512 out %04X %02X %04X:%04X\n",addr,val,CS,pc);
switch (addr)
{
- case 0x3d4:
+ case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6:
pc1512->crtcreg = val & 31;
return;
- case 0x3d5:
+ case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7:
old = pc1512->crtc[pc1512->crtcreg];
pc1512->crtc[pc1512->crtcreg] = val & crtcmask[pc1512->crtcreg];
if (old != val)
@@ -106,7 +107,8 @@ static uint8_t pc1512_in(uint16_t addr, void *p)
case 0x3d5:
return pc1512->crtc[pc1512->crtcreg];
case 0x3da:
- return pc1512->stat;
+ pc1512->stat ^= 0x01; /*Bit 0 is toggle bit on PC1512*/
+ return pc1512->stat ^ 0x01;
}
return 0xff;
}
@@ -147,7 +149,7 @@ static uint8_t pc1512_read(uint32_t addr, void *p)
static void pc1512_recalctimings(pc1512_t *pc1512)
{
double _dispontime, _dispofftime, disptime;
- disptime = 128; /*Fixed on PC1512*/
+ disptime = 114; /*Fixed on PC1512*/
_dispontime = 80;
_dispofftime = disptime - _dispontime;
// printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]);
@@ -173,7 +175,6 @@ static void pc1512_poll(void *p)
if (!pc1512->linepos)
{
timer_advance_u64(&pc1512->timer, pc1512->dispofftime);
- pc1512->stat |= 1;
pc1512->linepos = 1;
oldsc = pc1512->sc;
if (pc1512->dispon)
@@ -221,12 +222,12 @@ static void pc1512_poll(void *p)
if (drawcursor)
{
for (c = 0; c < 8; c++)
- ((uint32_t *)buffer32->line[pc1512->displine])[(x << 3) + c + 8] = cols[(fontdat[chr][pc1512->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
+ ((uint32_t *)buffer32->line[pc1512->displine])[(x << 3) + c + 8] = cols[(fontdat[chr + pc1512->fontbase][pc1512->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff;
}
else
{
for (c = 0; c < 8; c++)
- ((uint32_t *)buffer32->line[pc1512->displine])[(x << 3) + c + 8] = cols[(fontdat[chr][pc1512->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
+ ((uint32_t *)buffer32->line[pc1512->displine])[(x << 3) + c + 8] = cols[(fontdat[chr + pc1512->fontbase][pc1512->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
pc1512->ma++;
}
@@ -255,13 +256,13 @@ static void pc1512_poll(void *p)
{
for (c = 0; c < 8; c++)
((uint32_t *)buffer32->line[pc1512->displine])[(x << 4) + (c << 1) + 8] =
- ((uint32_t *)buffer32->line[pc1512->displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][pc1512->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff;
+ ((uint32_t *)buffer32->line[pc1512->displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + pc1512->fontbase][pc1512->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff;
}
else
{
for (c = 0; c < 8; c++)
((uint32_t *)buffer32->line[pc1512->displine])[(x << 4) + (c << 1) + 8] =
- ((uint32_t *)buffer32->line[pc1512->displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][pc1512->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
+ ((uint32_t *)buffer32->line[pc1512->displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + pc1512->fontbase][pc1512->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
@@ -341,8 +342,6 @@ static void pc1512_poll(void *p)
timer_advance_u64(&pc1512->timer, pc1512->dispontime);
if ((pc1512->lastline - pc1512->firstline) == 199)
pc1512->dispon = 0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/
- if (pc1512->dispon)
- pc1512->stat &= ~1;
pc1512->linepos = 0;
if (pc1512->vsynctime)
{
@@ -452,6 +451,7 @@ static void pc1512_poll(void *p)
static void *pc1512_init()
{
+ int display_type;
pc1512_t *pc1512 = malloc(sizeof(pc1512_t));
memset(pc1512, 0, sizeof(pc1512_t));
@@ -459,10 +459,13 @@ static void *pc1512_init()
pc1512->cgacol = 7;
pc1512->cgamode = 0x12;
-
+ pc1512->fontbase = (device_get_config_int("codepage") & 3) * 256;
+ display_type = device_get_config_int("display_type");
+
timer_add(&pc1512->timer, pc1512_poll, pc1512, 1);
mem_mapping_add(&pc1512->mapping, 0xb8000, 0x08000, pc1512_read, NULL, NULL, pc1512_write, NULL, NULL, NULL, 0, pc1512);
io_sethandler(0x03d0, 0x0010, pc1512_in, NULL, NULL, pc1512_out, NULL, NULL, pc1512);
+ cgapal_rebuild(display_type, 0);
return pc1512;
}
@@ -481,6 +484,57 @@ static void pc1512_speed_changed(void *p)
pc1512_recalctimings(pc1512);
}
+device_config_t pc1512_config[] =
+{
+ {
+ .name = "display_type",
+ .description = "Display type",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "PC-CM (Colour)",
+ .value = DISPLAY_RGB
+ },
+ {
+ .description = "PC-MM (Monochrome)",
+ .value = DISPLAY_WHITE
+ },
+ {
+ .description = ""
+ }
+ }
+ },
+ {
+ .name = "codepage",
+ .description = "Hardware font",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "US English",
+ .value = 3
+ },
+ {
+ .description = "Danish",
+ .value = 1
+ },
+ {
+ .description = "Greek",
+ .value = 0
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 3
+ },
+ {
+ .type = -1
+ }
+};
+
+
device_t pc1512_device =
{
"Amstrad PC1512 (video)",
@@ -490,5 +544,6 @@ device_t pc1512_device =
NULL,
pc1512_speed_changed,
NULL,
- NULL
+ NULL,
+ pc1512_config
};
diff --git a/src/vid_pc200.c b/src/vid_pc200.c
index 8f59dfc..e430232 100644
--- a/src/vid_pc200.c
+++ b/src/vid_pc200.c
@@ -1,23 +1,51 @@
-/*PC200 video emulation.
- CGA with some NMI stuff. But we don't need that as it's only used for TV and
- LCD displays, and we're emulating a CRT*/
+/*PC200/PPC video emulation. */
#include
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "mem.h"
+#include "nmi.h"
#include "timer.h"
#include "video.h"
#include "vid_cga.h"
+#include "vid_mda.h"
#include "vid_pc200.h"
+/* #define PC200LOG(x) pclog x */
+#define PC200LOG(x)
+
+/* Display type */
+#define PC200_CGA 0 /* CGA monitor */
+#define PC200_MDA 1 /* MDA monitor */
+#define PC200_TV 2 /* Television */
+#define PC200_LCDC 3 /* PPC512 LCD as CGA*/
+#define PC200_LCDM 4 /* PPC512 LCD as MDA*/
+
+int pc200_is_mda;
+
+static uint32_t blue, green;
+
+static uint32_t lcdcols[256][2][2];
+
typedef struct pc200_t
{
- mem_mapping_t mapping;
+ mem_mapping_t cga_mapping;
+ mem_mapping_t mda_mapping;
cga_t cga;
+ mda_t mda;
- uint8_t reg_3dd, reg_3de, reg_3df;
+ pc_timer_t timer;
+
+ uint8_t emulation; /* Which display are we emulating? */
+ uint8_t dipswitches; /* DIP switches 1-3 */
+ uint8_t crtc_index; /* CRTC index readback
+ * Bit 7: CGA control port written
+ * Bit 6: Operation control port written
+ * Bit 5: CRTC register written
+ * Bits 0-4: Last CRTC register selected */
+ uint8_t operation_ctrl;
+ uint8_t reg_3df;
} pc200_t;
static uint8_t crtcmask[32] =
@@ -26,24 +54,168 @@ static uint8_t crtcmask[32] =
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+/* LCD colour mappings
+ *
+ * 0 => solid green
+ * 1 => blue on green
+ * 2 => green on blue
+ * 3 => solid blue
+ */
+static unsigned char mapping1[256] =
+{
+/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+/*00*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/*10*/ 2, 0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
+/*20*/ 2, 2, 0, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1,
+/*30*/ 2, 2, 2, 0, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 1, 1,
+/*40*/ 2, 2, 1, 1, 0, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1,
+/*50*/ 2, 2, 1, 1, 2, 0, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1,
+/*60*/ 2, 2, 2, 2, 2, 2, 0, 1, 2, 2, 2, 2, 2, 2, 1, 1,
+/*70*/ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1,
+/*80*/ 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
+/*90*/ 2, 2, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 1, 1, 1, 1,
+/*A0*/ 2, 2, 2, 1, 2, 2, 1, 1, 2, 2, 0, 1, 2, 2, 1, 1,
+/*B0*/ 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 0, 2, 2, 1, 1,
+/*C0*/ 2, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 0, 1, 1, 1,
+/*D0*/ 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 0, 1, 1,
+/*E0*/ 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0, 1,
+/*F0*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+};
+
+static unsigned char mapping2[256] =
+{
+/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+/*00*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/*10*/ 1, 3, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2,
+/*20*/ 1, 1, 3, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2,
+/*30*/ 1, 1, 1, 3, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, 2, 2,
+/*40*/ 1, 1, 2, 2, 3, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2,
+/*50*/ 1, 1, 2, 2, 1, 3, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2,
+/*60*/ 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 2, 2,
+/*70*/ 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 2,
+/*80*/ 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
+/*90*/ 1, 1, 2, 2, 2, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2,
+/*A0*/ 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 3, 2, 1, 1, 2, 2,
+/*B0*/ 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 3, 1, 1, 2, 2,
+/*C0*/ 1, 1, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 3, 2, 2, 2,
+/*D0*/ 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 3, 2, 2,
+/*E0*/ 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 2,
+/*F0*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
+};
+
+static void set_lcd_cols(uint8_t mode_reg)
+{
+ unsigned char *mapping = (mode_reg & 0x80) ? mapping2 : mapping1;
+ int c;
+
+ for (c = 0; c < 256; c++)
+ {
+ switch (mapping[c])
+ {
+ case 0:
+ lcdcols[c][0][0] = lcdcols[c][1][0] = green;
+ lcdcols[c][0][1] = lcdcols[c][1][1] = green;
+ break;
+
+ case 1:
+ lcdcols[c][0][0] = lcdcols[c][1][0] =
+ lcdcols[c][1][1] = green;
+ lcdcols[c][0][1] = blue;
+ break;
+
+ case 2:
+ lcdcols[c][0][0] = lcdcols[c][1][0] =
+ lcdcols[c][1][1] = blue;
+ lcdcols[c][0][1] = green;
+ break;
+
+ case 3:
+ lcdcols[c][0][0] = lcdcols[c][1][0] = blue;
+ lcdcols[c][0][1] = lcdcols[c][1][1] = blue;
+ break;
+ }
+ }
+}
+
+
void pc200_out(uint16_t addr, uint8_t val, void *p)
{
pc200_t *pc200 = (pc200_t *)p;
cga_t *cga = &pc200->cga;
+ mda_t *mda = &pc200->mda;
uint8_t old;
-
+
+ PC200LOG(("pc200_out(0x%04x), %02x\n", addr, val));
+
+/* MDA writes ============================================================== */
switch (addr)
{
- case 0x3d5:
- if (!(pc200->reg_3de & 0x40) && cga->crtcreg <= 11)
+ case 0x3b1:
+ case 0x3b3:
+ case 0x3b5:
+ case 0x3b7:
+
+ /* Writes banned to CRTC registers 0-11? */
+ if (!(pc200->operation_ctrl & 0x40) && mda->crtcreg <= 11)
{
- if (pc200->reg_3de & 0x80)
+ pc200->crtc_index = 0x20 | (mda->crtcreg & 0x1f);
+ if (pc200->operation_ctrl & 0x80)
+ {
+ PC200LOG(("NMI raised from CRTC register access: reg=0x%02x val=0x%02x nmi_mask=%d\n", mda->crtcreg & 0x1F, val, nmi_mask));
nmi = 1;
-
- pc200->reg_3dd = 0x20 | (cga->crtcreg & 0x1f);
+ }
pc200->reg_3df = val;
return;
}
+ PC200LOG(("CRTM[%02x]:=%02x\n", mda->crtcreg, val));
+ old = mda->crtc[mda->crtcreg];
+ mda->crtc[mda->crtcreg] = val & crtcmask[mda->crtcreg];
+ if (old != val)
+ {
+ if (mda->crtcreg < 0xe || mda->crtcreg > 0x10)
+ {
+ fullchange = changeframecount;
+ mda_recalctimings(mda);
+ }
+ }
+ return;
+
+ case 0x3b8:
+ old = mda->ctrl;
+ mda->ctrl = val;
+ if ((mda->ctrl ^ old) & 3)
+ {
+ mda_recalctimings(mda);
+ }
+ pc200->crtc_index &= 0x1F;
+ pc200->crtc_index |= 0x80;
+ if (pc200->operation_ctrl & 0x80)
+ {
+ PC200LOG(("NMI raised from mode control access: val=0x%02x nmi_mask=%d\n", val, nmi_mask));
+ nmi = 1;
+ }
+ return;
+
+
+/* CGA writes ============================================================== */
+ case 0x3d1:
+ case 0x3d3:
+ case 0x3d5:
+ case 0x3d7:
+
+ /* Writes banned to CRTC registers 0-11? */
+ if (!(pc200->operation_ctrl & 0x40) && cga->crtcreg <= 11)
+ {
+ pc200->crtc_index = 0x20 | (cga->crtcreg & 0x1f);
+ if (pc200->operation_ctrl & 0x80)
+ {
+ PC200LOG(("NMI raised from CRTC register access: reg=0x%02x val=0x%02x nmi_mask=%d\n", cga->crtcreg & 0x1F, val, nmi_mask));
+ nmi = 1;
+ }
+ pc200->reg_3df = val;
+ return;
+ }
+ PC200LOG(("CRTC[%02x]:=%02x\n", cga->crtcreg, val));
old = cga->crtc[cga->crtcreg];
cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg];
if (old != val)
@@ -60,59 +232,656 @@ void pc200_out(uint16_t addr, uint8_t val, void *p)
old = cga->cgamode;
cga->cgamode = val;
if ((cga->cgamode ^ old) & 3)
- cga_recalctimings(cga);
- pc200->reg_3dd |= 0x80;
- if (pc200->reg_3de & 0x80)
- nmi = 1;
+ {
+ cga_recalctimings(cga);
+ }
+ pc200->crtc_index &= 0x1F;
+ pc200->crtc_index |= 0x80;
+ if (pc200->operation_ctrl & 0x80)
+ {
+ PC200LOG(("NMI raised from mode control access: val=0x%02x nmi_mask=%d\n", val, nmi_mask));
+ nmi = 1;
+ }
+ else set_lcd_cols(val);
return;
+/* PC200 control port writes ============================================== */
case 0x3de:
- pc200->reg_3de = val;
- pc200->reg_3dd = 0x1f;
- if (val & 0x80)
- pc200->reg_3dd |= 0x40;
+ pc200->crtc_index = 0x1f;
+/* NMI only seems to be triggered if the value being written has the high
+ * bit set (enable NMI). So it only protects writes to this port if you
+ * let it? */
+ if (val & 0x80)
+ {
+ PC200LOG(("NMI raised from operation control access: val=0x%02x nmi_mask=%d\n", val, nmi_mask));
+ pc200->operation_ctrl = val;
+ pc200->crtc_index |= 0x40;
+ nmi = 1;
+ return;
+ }
+ timer_disable(&pc200->cga.timer);
+ timer_disable(&pc200->mda.timer);
+ timer_disable(&pc200->timer);
+ pc200->operation_ctrl = val;
+ /* Bits 0 and 1 control emulation and output mode */
+ if (val & 1) /* Monitor */
+ {
+ pc200->emulation = (val & 2) ? PC200_MDA : PC200_CGA;
+ }
+ else if (romset == ROM_PPC512)
+ {
+ pc200->emulation = (val & 2) ? PC200_LCDM : PC200_LCDC;
+ }
+ else
+ {
+ pc200->emulation = PC200_TV;
+
+ }
+ PC200LOG(("Video emulation set to %d\n", pc200->emulation));
+ if (pc200->emulation == PC200_CGA || pc200->emulation == PC200_TV)
+ timer_advance_u64(&pc200->cga.timer, 1);
+ else if (pc200->emulation == PC200_MDA)
+ timer_advance_u64(&pc200->mda.timer, 1);
+ else
+ timer_advance_u64(&pc200->timer, 1);
+
+ /* Bit 2 disables the IDA. We don't support dynamic enabling
+ * and disabling of the IDA (instead, PCEM disconnects the
+ * IDA from the bus altogether) so don't implement this */
+
+ /* Enable the appropriate memory ranges depending whether
+ * the IDA is configured as MDA or CGA */
+ if (pc200->emulation == PC200_MDA ||
+ pc200->emulation == PC200_LCDM)
+ {
+ mem_mapping_disable(&pc200->cga_mapping);
+ mem_mapping_enable(&pc200->mda_mapping);
+ }
+ else
+ {
+ mem_mapping_disable(&pc200->mda_mapping);
+ mem_mapping_enable(&pc200->cga_mapping);
+ }
return;
}
- cga_out(addr, val, cga);
+ if (addr >= 0x3D0 && addr <= 0x3DF)
+ {
+ cga_out(addr, val, cga);
+ }
+ if (addr >= 0x3B0 && addr <= 0x3BB)
+ {
+ mda_out(addr, val, mda);
+ }
}
uint8_t pc200_in(uint16_t addr, void *p)
{
pc200_t *pc200 = (pc200_t *)p;
cga_t *cga = &pc200->cga;
+ mda_t *mda = &pc200->mda;
uint8_t temp;
+ PC200LOG(("pc200_in(0x%04x)\n", addr));
switch (addr)
{
+ case 0x3B8:
+ PC200LOG((" = %02x\n", mda->ctrl));
+ return mda->ctrl;
+
case 0x3D8:
+ PC200LOG((" = %02x\n", cga->cgamode));
return cga->cgamode;
case 0x3DD:
- temp = pc200->reg_3dd;
- pc200->reg_3dd &= 0x1f;
- nmi = 0;
+ temp = pc200->crtc_index; /* Read NMI reason */
+ pc200->crtc_index &= 0x1f; /* Reset NMI reason */
+ nmi = 0; /* And reset NMI flag */
+ PC200LOG((" = %02x\n", temp));
return temp;
case 0x3DE:
- return (pc200->reg_3de & 0xc7) | 0x10; /*External CGA*/
-
+ PC200LOG((" = %02x\n", ((pc200->operation_ctrl & 0xc7) | pc200->dipswitches)));
+ return ((pc200->operation_ctrl & 0xc7) | pc200->dipswitches);
+
case 0x3DF:
return pc200->reg_3df;
}
- return cga_in(addr, cga);
+ if (addr >= 0x3D0 && addr <= 0x3DF)
+ {
+ return cga_in(addr, cga);
+ }
+ if (addr >= 0x3B0 && addr <= 0x3BB)
+ {
+ return mda_in(addr, mda);
+ }
+ return 0xFF;
+}
+
+void lcd_draw_char_80(pc200_t *pc200, uint32_t *buffer, uint8_t chr,
+ uint8_t attr, int drawcursor, int blink, int sc,
+ int mode160, uint8_t control)
+{
+ int c;
+ uint8_t bits = fontdat[chr + pc200->cga.fontbase][sc];
+ uint8_t bright = 0;
+ uint16_t mask;
+
+ if (attr & 8) /* bright */
+ {
+/* The brightness algorithm appears to be: replace any bit sequence 011
+ * with 001 (assuming an extra 0 to the left of the byte).
+ */
+ bright = bits;
+ for (c = 0, mask = 0x100; c < 7; c++, mask >>= 1)
+ {
+ if (((bits & mask) == 0) &&
+ ((bits & (mask >> 1)) != 0) &&
+ ((bits & (mask >> 2)) != 0))
+ {
+ bright &= ~(mask >> 1);
+ }
+ }
+ bits = bright;
+ }
+
+ if (drawcursor) bits ^= 0xFF;
+
+ for (c = 0, mask = 0x80; c < 8; c++, mask >>= 1)
+ {
+ if (mode160)
+ buffer[c] = (attr & mask) ? blue : green;
+ else if (control & 0x20) /* blinking */
+ buffer[c] = lcdcols[attr & 0x7F][blink][(bits & mask) ? 1 : 0];
+ else
+ buffer[c] = lcdcols[attr][blink][(bits & mask) ? 1 : 0];
+ }
+}
+
+
+void lcd_draw_char_40(pc200_t *pc200, uint32_t *buffer, uint8_t chr,
+ uint8_t attr, int drawcursor, int blink, int sc,
+ uint8_t control)
+{
+ int c;
+ uint8_t bits = fontdat[chr + pc200->cga.fontbase][sc];
+ uint8_t mask = 0x80;
+
+ if (attr & 8) /* bright */
+ {
+ bits = bits & (bits >> 1);
+ }
+ if (drawcursor) bits ^= 0xFF;
+
+ for (c = 0; c < 8; c++, mask >>= 1)
+ {
+ if (control & 0x20)
+ {
+ buffer[c*2] = buffer[c*2+1] =
+ lcdcols[attr & 0x7F][blink][(bits & mask) ? 1 : 0];
+ }
+ else
+ {
+ buffer[c*2] = buffer[c*2+1] =
+ lcdcols[attr][blink][(bits & mask) ? 1 : 0];
+ }
+ }
+}
+
+void lcdm_poll(pc200_t *pc200)
+{
+ mda_t *mda = &pc200->mda;
+ uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff;
+ int drawcursor;
+ int x;
+ int oldvc;
+ uint8_t chr, attr;
+ int oldsc;
+ int blink;
+ if (!mda->linepos)
+ {
+ timer_advance_u64(&pc200->timer, mda->dispofftime);
+ mda->stat |= 1;
+ mda->linepos = 1;
+ oldsc = mda->sc;
+ if ((mda->crtc[8] & 3) == 3)
+ mda->sc = (mda->sc << 1) & 7;
+ if (mda->dispon)
+ {
+ if (mda->displine < mda->firstline)
+ {
+ mda->firstline = mda->displine;
+ video_wait_for_buffer();
+ }
+ mda->lastline = mda->displine;
+ for (x = 0; x < mda->crtc[1]; x++)
+ {
+ chr = mda->vram[(mda->ma << 1) & 0xfff];
+ attr = mda->vram[((mda->ma << 1) + 1) & 0xfff];
+ drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron);
+ blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
+
+ lcd_draw_char_80(pc200, &((uint32_t *)(buffer32->line[mda->displine]))[x * 8], chr, attr, drawcursor, blink, mda->sc, 0, mda->ctrl);
+ mda->ma++;
+ }
+ }
+ mda->sc = oldsc;
+ if (mda->vc == mda->crtc[7] && !mda->sc)
+ {
+ mda->stat |= 8;
+// printf("VSYNC on %i %i\n",vc,sc);
+ }
+ mda->displine++;
+ if (mda->displine >= 500)
+ mda->displine=0;
+ }
+ else
+ {
+ timer_advance_u64(&pc200->timer, mda->dispontime);
+ if (mda->dispon) mda->stat&=~1;
+ mda->linepos=0;
+ if (mda->vsynctime)
+ {
+ mda->vsynctime--;
+ if (!mda->vsynctime)
+ {
+ mda->stat&=~8;
+// printf("VSYNC off %i %i\n",vc,sc);
+ }
+ }
+ if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1)))
+ {
+ mda->con = 0;
+ mda->coff = 1;
+ }
+ if (mda->vadj)
+ {
+ mda->sc++;
+ mda->sc &= 31;
+ mda->ma = mda->maback;
+ mda->vadj--;
+ if (!mda->vadj)
+ {
+ mda->dispon = 1;
+ mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
+ mda->sc = 0;
+ }
+ }
+ else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1)))
+ {
+ mda->maback = mda->ma;
+ mda->sc = 0;
+ oldvc = mda->vc;
+ mda->vc++;
+ mda->vc &= 127;
+ if (mda->vc == mda->crtc[6])
+ mda->dispon=0;
+ if (oldvc == mda->crtc[4])
+ {
+// printf("Display over at %i\n",displine);
+ mda->vc = 0;
+ mda->vadj = mda->crtc[5];
+ if (!mda->vadj) mda->dispon = 1;
+ if (!mda->vadj) mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
+ if ((mda->crtc[10] & 0x60) == 0x20) mda->cursoron = 0;
+ else mda->cursoron = mda->blink & 16;
+ }
+ if (mda->vc == mda->crtc[7])
+ {
+ mda->dispon = 0;
+ mda->displine = 0;
+ mda->vsynctime = 16;
+ if (mda->crtc[7])
+ {
+// printf("Lastline %i Firstline %i %i\n",lastline,firstline,lastline-firstline);
+ x = mda->crtc[1] * 8;
+ mda->lastline++;
+ if (x != xsize || (mda->lastline - mda->firstline) != ysize)
+ {
+ xsize = x;
+ ysize = mda->lastline - mda->firstline;
+// printf("Resize to %i,%i - R1 %i\n",xsize,ysize,crtcm[1]);
+ if (xsize < 64) xsize = 656;
+ if (ysize < 32) ysize = 200;
+ updatewindowsize(xsize, ysize << 1);
+ }
+
+ video_blit_memtoscreen(0, mda->firstline, 0, ysize, xsize, ysize);
+
+ frames++;
+ video_res_x = mda->crtc[1];
+ video_res_y = mda->crtc[6];
+ video_bpp = 0;
+ }
+ mda->firstline = 1000;
+ mda->lastline = 0;
+ mda->blink++;
+ }
+ }
+ else
+ {
+ mda->sc++;
+ mda->sc &= 31;
+ mda->ma = mda->maback;
+ }
+ if ((mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1))))
+ {
+ mda->con = 1;
+// printf("Cursor on - %02X %02X %02X\n",crtcm[8],crtcm[10],crtcm[11]);
+ }
+ }
+}
+
+void lcdc_poll(pc200_t *pc200)
+{
+ cga_t *cga = &pc200->cga;
+ int drawcursor;
+ int x, c;
+ int oldvc;
+ uint8_t chr, attr;
+ uint16_t dat;
+ int oldsc;
+ uint16_t ca;
+ int blink;
+
+ ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff;
+
+ if (!cga->linepos)
+ {
+ timer_advance_u64(&pc200->timer, cga->dispofftime);
+ cga->cgastat |= 1;
+ cga->linepos = 1;
+ oldsc = cga->sc;
+ if ((cga->crtc[8] & 3) == 3)
+ cga->sc = ((cga->sc << 1) + cga->oddeven) & 7;
+ if (cga->cgadispon)
+ {
+ if (cga->displine < cga->firstline)
+ {
+ cga->firstline = cga->displine;
+ video_wait_for_buffer();
+// printf("Firstline %i\n",firstline);
+ }
+ cga->lastline = cga->displine;
+
+ if (cga->cgamode & 1)
+ {
+ for (x = 0; x < cga->crtc[1]; x++)
+ {
+ chr = cga->charbuffer[x << 1];
+ attr = cga->charbuffer[(x << 1) + 1];
+ drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
+ blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor);
+ lcd_draw_char_80(pc200, &((uint32_t *)(buffer32->line[cga->displine]))[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode);
+ cga->ma++;
+ }
+ }
+ else if (!(cga->cgamode & 2))
+ {
+ for (x = 0; x < cga->crtc[1]; x++)
+ {
+ chr = cga->vram[((cga->ma << 1) & 0x3fff)];
+ attr = cga->vram[(((cga->ma << 1) + 1) & 0x3fff)];
+ drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
+ blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor);
+ lcd_draw_char_40(pc200, &((uint32_t *)(buffer32->line[cga->displine]))[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode);
+ cga->ma++;
+ }
+ }
+ else /* Graphics mode */
+ {
+ for (x = 0; x < cga->crtc[1]; x++)
+ {
+ dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
+ cga->ma++;
+ for (c = 0; c < 16; c++)
+ {
+ ((uint32_t *)buffer32->line[cga->displine])[(x << 4) + c] = (dat & 0x8000) ? blue : green;
+ dat <<= 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (cga->cgamode & 1) hline(buffer32, 0, cga->displine, (cga->crtc[1] << 3), green);
+ else hline(buffer32, 0, cga->displine, (cga->crtc[1] << 4), green);
+ }
+
+ if (cga->cgamode & 1) x = (cga->crtc[1] << 3);
+ else x = (cga->crtc[1] << 4);
+
+ cga->sc = oldsc;
+ if (cga->vc == cga->crtc[7] && !cga->sc)
+ cga->cgastat |= 8;
+ cga->displine++;
+ if (cga->displine >= 360)
+ cga->displine = 0;
+ }
+ else
+ {
+ timer_advance_u64(&pc200->timer, cga->dispontime);
+ cga->linepos = 0;
+ if (cga->vsynctime)
+ {
+ cga->vsynctime--;
+ if (!cga->vsynctime)
+ cga->cgastat &= ~8;
+ }
+ if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1)))
+ {
+ cga->con = 0;
+ cga->coff = 1;
+ }
+ if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1))
+ cga->maback = cga->ma;
+ if (cga->vadj)
+ {
+ cga->sc++;
+ cga->sc &= 31;
+ cga->ma = cga->maback;
+ cga->vadj--;
+ if (!cga->vadj)
+ {
+ cga->cgadispon = 1;
+ cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
+ cga->sc = 0;
+ }
+ }
+ else if (cga->sc == cga->crtc[9])
+ {
+ cga->maback = cga->ma;
+ cga->sc = 0;
+ oldvc = cga->vc;
+ cga->vc++;
+ cga->vc &= 127;
+
+ if (cga->vc == cga->crtc[6])
+ cga->cgadispon = 0;
+
+ if (oldvc == cga->crtc[4])
+ {
+ cga->vc = 0;
+ cga->vadj = cga->crtc[5];
+ if (!cga->vadj) cga->cgadispon = 1;
+ if (!cga->vadj) cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
+ if ((cga->crtc[10] & 0x60) == 0x20) cga->cursoron = 0;
+ else cga->cursoron = cga->cgablink & 8;
+ }
+
+ if (cga->vc == cga->crtc[7])
+ {
+ cga->cgadispon = 0;
+ cga->displine = 0;
+ cga->vsynctime = 16;
+ if (cga->crtc[7])
+ {
+ if (cga->cgamode & 1) x = (cga->crtc[1] << 3);
+ else x = (cga->crtc[1] << 4);
+ cga->lastline++;
+ if (x != xsize || (cga->lastline - cga->firstline) != ysize)
+ {
+ xsize = x;
+ ysize = cga->lastline - cga->firstline;
+ if (xsize < 64) xsize = 656;
+ if (ysize < 32) ysize = 200;
+ updatewindowsize(xsize, (ysize << 1));
+ }
+
+ video_blit_memtoscreen(0, cga->firstline, 0, (cga->lastline - cga->firstline), xsize, (cga->lastline - cga->firstline));
+ frames++;
+
+ video_res_x = xsize - 16;
+ video_res_y = ysize;
+ if (cga->cgamode & 1)
+ {
+ video_res_x /= 8;
+ video_res_y /= cga->crtc[9] + 1;
+ video_bpp = 0;
+ }
+ else if (!(cga->cgamode & 2))
+ {
+ video_res_x /= 16;
+ video_res_y /= cga->crtc[9] + 1;
+ video_bpp = 0;
+ }
+ else if (!(cga->cgamode & 16))
+ {
+ video_res_x /= 2;
+ video_bpp = 2;
+ }
+ else
+ {
+ video_bpp = 1;
+ }
+ }
+ cga->firstline = 1000;
+ cga->lastline = 0;
+ cga->cgablink++;
+ cga->oddeven ^= 1;
+ }
+ }
+ else
+ {
+ cga->sc++;
+ cga->sc &= 31;
+ cga->ma = cga->maback;
+ }
+ if (cga->cgadispon)
+ cga->cgastat &= ~1;
+ if ((cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1))))
+ cga->con = 1;
+ if (cga->cgadispon && (cga->cgamode & 1))
+ {
+ for (x = 0; x < (cga->crtc[1] << 1); x++)
+ cga->charbuffer[x] = cga->vram[(((cga->ma << 1) + x) & 0x3fff)];
+ }
+ }
+
+}
+
+void pc200_poll(void *p)
+{
+ pc200_t *pc200 = (pc200_t *)p;
+
+ switch (pc200->emulation)
+ {
+// case PC200_CGA:
+// case PC200_TV:
+// pc200->cga.vidtime = pc200->vidtime;
+// cga_poll(&pc200->cga);
+// pc200->vidtime = pc200->cga.vidtime;
+// return;
+
+// case PC200_MDA:
+// pc200->mda.vidtime = pc200->vidtime;
+// mda_poll(&pc200->mda);
+// pc200->vidtime = pc200->mda.vidtime;
+// return;
+
+ case PC200_LCDM:
+ lcdm_poll(pc200);
+ return;
+ case PC200_LCDC:
+ lcdc_poll(pc200);
+ return;
+ }
}
void *pc200_init()
{
+ int display_type, contrast;
+
pc200_t *pc200 = malloc(sizeof(pc200_t));
- cga_t *cga = &pc200->cga;
+
memset(pc200, 0, sizeof(pc200_t));
- pc200->cga.vram = malloc(0x4000);
+ pc200->emulation = device_get_config_int("video_emulation");
+ display_type = device_get_config_int("display_type");
+ contrast = device_get_config_int("contrast");
+
+ /* Default to CGA */
+ pc200->dipswitches = 0x10;
+
+ /* DIP switches for PC200. Switches 2,3 give video emulation.
+ * Switch 1 is 'swap floppy drives' (not implemented) */
+ if (romset == ROM_PC200) switch (pc200->emulation)
+ {
+ case PC200_CGA: pc200->dipswitches = 0x10; break;
+ case PC200_MDA: pc200->dipswitches = 0x30; break;
+ case PC200_TV: pc200->dipswitches = 0x00; break;
+ /* The other combination is 'IDA disabled' (0x20) - see
+ * amstrad.c */
+ }
+ /* DIP switches for PPC512. Switch 1 is CRT/LCD. Switch 2
+ * is MDA / CGA. Switch 3 disables IDA, not implemented. */
+ else switch (pc200->emulation)
+ {
+ case PC200_CGA: pc200->dipswitches = 0x08; break;
+ case PC200_MDA: pc200->dipswitches = 0x18; break;
+ case PC200_LCDC: pc200->dipswitches = 0x00; break;
+ case PC200_LCDM: pc200->dipswitches = 0x10; break;
+ }
+ /* Flag whether the card is behaving like a CGA or an MDA, so that
+ * DIP switches are reported correctly */
+ pc200_is_mda = (pc200->emulation == PC200_MDA ||
+ pc200->emulation == PC200_LCDM);
+ PC200LOG(("pc200: DIP switches = %02x\n", pc200->dipswitches));
+
+ pc200->cga.vram = pc200->mda.vram = malloc(0x4000);
cga_init(&pc200->cga);
-
- mem_mapping_add(&pc200->mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga);
+ mda_init(&pc200->mda);
+
+ /* Attribute 8 is white on black (on a real MDA it's black on black) */
+ mda_setcol(0x08, 0, 1, 15);
+ mda_setcol(0x88, 0, 1, 15);
+ /* Attribute 64 is black on black (on a real MDA it's white on black) */
+ mda_setcol(0x40, 0, 1, 0);
+ mda_setcol(0xC0, 0, 1, 0);
+
+ pc200->cga.fontbase = (device_get_config_int("codepage") & 3) * 256;
+
+// pclog("pc200=%p pc200->timer=%p pc200->cga=%p pc200->mda=%p pc200->mda->timer=%p\n", pc200, &pc200->timer, &pc200->cga, &pc200->mda, &pc200->mda->timer);
+ timer_add(&pc200->timer, pc200_poll, pc200, 1);
+ mem_mapping_add(&pc200->mda_mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, 0, &pc200->mda);
+ mem_mapping_add(&pc200->cga_mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, &pc200->cga);
io_sethandler(0x03d0, 0x0010, pc200_in, NULL, NULL, pc200_out, NULL, NULL, pc200);
+ io_sethandler(0x03b0, 0x000c, pc200_in, NULL, NULL, pc200_out, NULL, NULL, pc200);
+
+ green = makecol(0x1C, 0x71, 0x31);
+ blue = makecol(0x0f, 0x21, 0x3f);
+ cgapal_rebuild(display_type, contrast);
+ set_lcd_cols(0);
+
+ timer_disable(&pc200->cga.timer);
+ timer_disable(&pc200->mda.timer);
+ timer_disable(&pc200->timer);
+ if (pc200->emulation == PC200_CGA || pc200->emulation == PC200_TV)
+ timer_enable(&pc200->cga.timer);
+ else if (pc200->emulation == PC200_MDA)
+ timer_enable(&pc200->mda.timer);
+ else
+ timer_enable(&pc200->timer);
+
return pc200;
}
@@ -129,8 +898,198 @@ void pc200_speed_changed(void *p)
pc200_t *pc200 = (pc200_t *)p;
cga_recalctimings(&pc200->cga);
+ mda_recalctimings(&pc200->mda);
}
+device_config_t pc200_config[] =
+{
+ {
+ .name = "video_emulation",
+ .description = "Display type",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "CGA monitor",
+ .value = PC200_CGA,
+ },
+ {
+ .description = "MDA monitor",
+ .value = PC200_MDA,
+ },
+ {
+ .description = "Television",
+ .value = PC200_TV,
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = PC200_CGA,
+ },
+ {
+ .name = "display_type",
+ .description = "Monitor type",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "RGB",
+ .value = DISPLAY_RGB
+ },
+ {
+ .description = "RGB (no brown)",
+ .value = DISPLAY_RGB_NO_BROWN
+ },
+ {
+ .description = "Green Monochrome",
+ .value = DISPLAY_GREEN
+ },
+ {
+ .description = "Amber Monochrome",
+ .value = DISPLAY_AMBER
+ },
+ {
+ .description = "White Monochrome",
+ .value = DISPLAY_WHITE
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = DISPLAY_RGB
+ },
+ {
+ .name = "codepage",
+ .description = "Hardware font",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "US English",
+ .value = 3
+ },
+ {
+ .description = "Portugese",
+ .value = 2
+ },
+ {
+ .description = "Norwegian",
+ .value = 1
+ },
+ {
+ .description = "Greek",
+ .value = 0
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 3
+ },
+ {
+ .type = -1
+ }
+};
+
+
+device_config_t ppc512_config[] =
+{
+ {
+ .name = "video_emulation",
+ .description = "Display type",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "CGA monitor",
+ .value = PC200_CGA,
+ },
+ {
+ .description = "MDA monitor",
+ .value = PC200_MDA,
+ },
+ {
+ .description = "LCD (CGA mode)",
+ .value = PC200_LCDC,
+ },
+ {
+ .description = "LCD (MDA mode)",
+ .value = PC200_LCDM,
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = PC200_LCDC,
+ },
+ {
+ .name = "display_type",
+ .description = "External monitor",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "RGB",
+ .value = DISPLAY_RGB
+ },
+ {
+ .description = "RGB (no brown)",
+ .value = DISPLAY_RGB_NO_BROWN
+ },
+ {
+ .description = "Green Monochrome",
+ .value = DISPLAY_GREEN
+ },
+ {
+ .description = "Amber Monochrome",
+ .value = DISPLAY_AMBER
+ },
+ {
+ .description = "White Monochrome",
+ .value = DISPLAY_WHITE
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = DISPLAY_RGB
+ },
+ {
+ .name = "codepage",
+ .description = "Hardware font",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "US English",
+ .value = 3
+ },
+ {
+ .description = "Portugese",
+ .value = 2
+ },
+ {
+ .description = "Norwegian",
+ .value = 1
+ },
+ {
+ .description = "Greek",
+ .value = 0
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 3
+ },
+ {
+ .type = -1
+ }
+};
+
+
+
device_t pc200_device =
{
"Amstrad PC200 (video)",
@@ -140,5 +1099,20 @@ device_t pc200_device =
NULL,
pc200_speed_changed,
NULL,
- NULL
+ NULL,
+ pc200_config
};
+
+device_t ppc512_device =
+{
+ "Amstrad PPC512 (video)",
+ 0,
+ pc200_init,
+ pc200_close,
+ NULL,
+ pc200_speed_changed,
+ NULL,
+ NULL,
+ ppc512_config
+};
+
diff --git a/src/vid_pc200.h b/src/vid_pc200.h
index 4b43090..f59de48 100644
--- a/src/vid_pc200.h
+++ b/src/vid_pc200.h
@@ -1 +1,4 @@
extern device_t pc200_device;
+extern device_t ppc512_device;
+
+extern int pc200_is_mda;
diff --git a/src/vid_pgc.c b/src/vid_pgc.c
new file mode 100644
index 0000000..5f61dfa
--- /dev/null
+++ b/src/vid_pgc.c
@@ -0,0 +1,2477 @@
+/*PGC emulation*/
+#include
+#include
+#include
+#include "ibm.h"
+#include "device.h"
+#include "io.h"
+#include "mem.h"
+#include "timer.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_pgc.h"
+#include
+
+/* This implements just enough of the Professional Graphics Controller to
+ * act as a basis for the Vermont Microsystems IM-1024.
+ *
+ * PGC features implemented include:
+ * > The CGA-compatible display modes
+ * > Switching to and from native mode
+ * > Communicating with the host PC
+ *
+ * Numerous features are implemented partially or not at all, such as:
+ * > 2D drawing
+ * > 3D drawing
+ * > Command lists
+ * Some of these are marked TODO.
+ *
+ * The PGC has two display modes: CGA (in which it appears in the normal CGA
+ * memory and I/O ranges) and native (in which all functions are accessed
+ * through reads and writes to 1k of memory at 0xC6000). The PGC's 8088
+ * processor monitors this buffer and executes instructions left there
+ * for it. We simulate this behaviour with a separate thread.
+ */
+
+#define PGC_CGA_WIDTH 640
+#define PGC_CGA_HEIGHT 400
+
+static int pgc_parse_command(pgc_core_t *pgc, const pgc_command_t **pcmd);
+int pgc_clist_byte(pgc_core_t *pgc, uint8_t *val);
+
+
+
+
+static const char *pgc_err_msgs[] =
+{
+ "Range \r",
+ "Integer \r",
+ "Memory \r",
+ "Overflow\r",
+ "Digit \r",
+ "Opcode \r",
+ "Running \r",
+ "Stack \r",
+ "Too long\r",
+ "Area \r",
+ "Missing \r"
+};
+
+#define HWORD(u) ((u) >> 16)
+#define LWORD(u) ((u) & 0xFFFF)
+
+
+/* Initial palettes */
+uint32_t init_palette[6][256] =
+{
+#include "pgc_palettes.h"
+};
+
+
+
+/* When idle, the PGC drawing thread sleeps. pgc_wake() awakens it - but
+ * not immediately. Like the Voodoo, it has a short delay so that writes
+ * can be batched */
+#define WAKE_DELAY (TIMER_USEC * 500)
+void pgc_wake(pgc_core_t *pgc)
+{
+ if (!timer_is_enabled(&pgc->wake_timer))
+ {
+ timer_set_delay_u64(&pgc->wake_timer, WAKE_DELAY);
+ }
+}
+
+
+/* When the wake timer expires, that's when the drawing thread is actually
+ * woken */
+static void pgc_wake_timer(void *p)
+{
+ pgc_core_t *pgc = (pgc_core_t *)p;
+
+ PGCLOG(("pgc: Waking up\n"));
+ thread_set_event(pgc->pgc_wake_thread);
+}
+
+/* This is called by the drawing thread when it's waiting for the host
+ * to put more input in its input FIFO, or drain output from its output
+ * FIFO. */
+void pgc_sleep(pgc_core_t *pgc)
+{
+
+ PGCLOG(("pgc: Sleeping on %d %d %d 0x%02x 0x%02x\n",
+ pgc->waiting_input_fifo,
+ pgc->waiting_output_fifo,
+ pgc->waiting_error_fifo,
+ pgc->mapram[0x300], pgc->mapram[0x301]));
+ /* Race condition: If host wrote to the PGC during the pclog() that
+ * won't be noticed */
+ if (pgc->waiting_input_fifo && pgc->mapram[0x300] != pgc->mapram[0x301])
+ {
+ pgc->waiting_input_fifo = 0;
+ return;
+ }
+ /* Same if they read */
+ if (pgc->waiting_output_fifo && pgc->mapram[0x302] != (uint8_t)(pgc->mapram[0x303] - 1))
+ {
+ pgc->waiting_output_fifo = 0;
+ return;
+ }
+ thread_wait_event(pgc->pgc_wake_thread, -1);
+ thread_reset_event(pgc->pgc_wake_thread);
+
+}
+
+/* Switch between CGA mode (DISPLAY 1) and native mode (DISPLAY 0) */
+void pgc_setdisplay(pgc_core_t *pgc, int cga)
+{
+ PGCLOG(("pgc_setdisplay(%d): cga_selected=%d cga_enabled=%d\n",
+ cga, pgc->cga_selected, pgc->cga_enabled));
+ if (pgc->cga_selected != (pgc->cga_enabled && cga))
+ {
+ pgc->cga_selected = (pgc->cga_enabled && cga);
+
+ if (pgc->cga_selected)
+ {
+ mem_mapping_enable(&pgc->cga_mapping);
+ pgc->screenw = PGC_CGA_WIDTH;
+ pgc->screenh = PGC_CGA_HEIGHT;
+ }
+ else
+ {
+ mem_mapping_disable(&pgc->cga_mapping);
+ pgc->screenw = pgc->visw;
+ pgc->screenh = pgc->vish;
+ }
+ pgc_recalctimings(pgc);
+ }
+}
+
+
+
+
+
+/* Convert coordinates based on the current window / viewport to raster
+ * coordinates. */
+void pgc_dto_raster(pgc_core_t *pgc, double *x, double *y)
+{
+/* double x0 = *x, y0 = *y; */
+
+ *x += (pgc->vp_x1 - pgc->win_x1);
+ *y += (pgc->vp_y1 - pgc->win_y1);
+
+/* PGCLOG(("Coords to raster: (%f, %f) -> (%f, %f)\n", x0, y0, *x, *y)); */
+}
+
+
+/* Overloads that take ints */
+void pgc_sto_raster(pgc_core_t *pgc, int16_t *x, int16_t *y)
+{
+ double xd = *x, yd = *y;
+
+ pgc_dto_raster(pgc, &xd, &yd);
+ *x = (int16_t)xd;
+ *y = (int16_t)yd;
+}
+
+void pgc_ito_raster(pgc_core_t *pgc, int32_t *x, int32_t *y)
+{
+ double xd = *x, yd = *y;
+
+ pgc_dto_raster(pgc, &xd, &yd);
+ *x = (int32_t)xd;
+ *y = (int32_t)yd;
+}
+
+
+/* Add a byte to a command list. We allow command lists to be
+ * arbitrarily large */
+int pgc_commandlist_append(pgc_commandlist_t *list, uint8_t v)
+{
+ if (list->listmax == 0 || list->list == NULL)
+ {
+ list->list = malloc(4096);
+ if (!list->list)
+ {
+ PGCLOG(("Out of memory initialising command list\n"));
+ return 0;
+ }
+ list->listmax = 4096;
+ }
+ while (list->wrptr >= list->listmax)
+ {
+ uint8_t *buf = realloc(list->list, 2 * list->listmax);
+ if (!buf)
+ {
+ PGCLOG(("Out of memory growing command list\n"));
+ return 0;
+ }
+ list->list = buf;
+ list->listmax *= 2;
+ }
+ list->list[list->wrptr++] = v;
+ return 1;
+}
+
+/* Beginning of a command list. Parse commands up to the next CLEND,
+ * storing them (in hex form) in the named command list. */
+static void hndl_clbeg(pgc_core_t *pgc)
+{
+ uint8_t param;
+ pgc_commandlist_t cl;
+ const pgc_command_t *cmd;
+
+ memset(&cl, 0, sizeof(cl));
+ if (!pgc_param_byte(pgc, ¶m)) return;
+
+ PGCLOG(("CLBEG(%d)\n", param));
+ while (1)
+ {
+ if (!pgc_parse_command(pgc, &cmd))
+ {
+ /* PGC has been reset */
+ return;
+ }
+ if (!cmd)
+ {
+ pgc_error(pgc, PGC_ERROR_OPCODE);
+ return;
+ }
+ else if (pgc->hex_command == 0x71) /* CLEND */
+ {
+ pgc->clist[param] = cl;
+ return;
+ }
+ else
+ {
+ if (!pgc_commandlist_append(&cl, pgc->hex_command))
+ {
+ pgc_error(pgc, PGC_ERROR_OVERFLOW);
+ return;
+ }
+ if (cmd->parser)
+ {
+ if (!(*cmd->parser)(pgc, &cl, cmd->p))
+ {
+ return;
+ }
+ }
+ }
+ }
+}
+
+static void hndl_clend(pgc_core_t *pgc)
+{
+ /* Shouldn't happen outside a CLBEG */
+}
+
+/* Execute a command list. If one was already executing, remember it so
+ * we can return to it afterwards. */
+static void hndl_clrun(pgc_core_t *pgc)
+{
+ uint8_t param;
+ pgc_commandlist_t *clprev = pgc->clcur;
+
+ if (!pgc_param_byte(pgc, ¶m)) return;
+
+ pgc->clcur = &pgc->clist[param];
+ pgc->clcur->rdptr = 0;
+ pgc->clcur->repeat = 1;
+ pgc->clcur->chain = clprev;
+}
+
+/* Execute a command list multiple times. */
+static void hndl_cloop(pgc_core_t *pgc)
+{
+ uint8_t param;
+ int16_t repeat;
+ pgc_commandlist_t *clprev = pgc->clcur;
+
+ if (!pgc_param_byte(pgc, ¶m)) return;
+ if (!pgc_param_word(pgc, &repeat)) return;
+
+ pgc->clcur = &pgc->clist[param];
+ pgc->clcur->rdptr = 0;
+ pgc->clcur->repeat = repeat;
+ pgc->clcur->chain = clprev;
+}
+
+
+/* Read back a command list */
+static void hndl_clread(pgc_core_t *pgc)
+{
+ uint8_t param;
+ int n;
+
+ if (!pgc_param_byte(pgc, ¶m)) return;
+
+ for (n = 0; n < pgc->clist[param].wrptr; n++)
+ {
+ if (!pgc_result_byte(pgc, pgc->clist[param].list[n]))
+ return;
+ }
+}
+
+
+/* Delete a command list */
+static void hndl_cldel(pgc_core_t *pgc)
+{
+ uint8_t param;
+
+ if (!pgc_param_byte(pgc, ¶m)) return;
+ memset(&pgc->clist[param], 0, sizeof(pgc_commandlist_t));
+}
+
+
+
+/* Clear the screen to a specified colour */
+static void hndl_clears(pgc_core_t *pgc)
+{
+ uint8_t param;
+ int y;
+
+ if (!pgc_param_byte(pgc, ¶m)) return;
+
+ for (y = 0; y < pgc->screenh; y++)
+ memset(pgc->vram + y * pgc->maxw, param, pgc->screenw);
+}
+
+/* Select drawing colour */
+static void hndl_color(pgc_core_t *pgc)
+{
+ uint8_t param;
+
+ if (!pgc_param_byte(pgc, ¶m)) return;
+
+ pgc->colour = param;
+ PGCLOG(("COLOR(%d)\n", param));
+}
+
+
+/* Set drawing mode.
+ *
+ * 0 => Draw
+ * 1 => Invert
+ * 2 => XOR (IM-1024)
+ * 3 => AND (IM-1024)
+ *
+ */
+static void hndl_linfun(pgc_core_t *pgc)
+{
+ uint8_t param;
+
+ if (!pgc_param_byte(pgc, ¶m)) return;
+
+ /* TODO: Not range-checked. Strictly speaking we should limit to 0-1
+ * for the PGC and 0-3 for the IM-1024. */
+ pgc->draw_mode = param;
+ PGCLOG(("LINFUN(%d)\n", param));
+}
+
+/* Set the line drawing pattern */
+static void hndl_linpat(pgc_core_t *pgc)
+{
+ uint16_t param;
+
+ if (!pgc_param_word(pgc, (int16_t *)¶m)) return;
+
+ pgc->line_pattern = param;
+ PGCLOG(("LINPAT(0x%04x)\n", param));
+}
+
+/* Set the polygon fill mode (0=hollow, 1=filled, 2=fast fill) */
+static void hndl_prmfil(pgc_core_t *pgc)
+{
+ uint8_t param;
+
+ if (!pgc_param_byte(pgc, ¶m)) return;
+
+ PGCLOG(("PRMFIL(%d)\n", param));
+ if (param < 3)
+ {
+ pgc->fill_mode = param;
+ }
+ else
+ {
+ pgc_error(pgc, PGC_ERROR_RANGE);
+ }
+}
+
+
+/* Set the 2D drawing position */
+static void hndl_move(pgc_core_t *pgc)
+{
+ int32_t x = 0, y = 0;
+
+ if (!pgc_param_coord(pgc, &x)) return;
+ if (!pgc_param_coord(pgc, &y)) return;
+
+ pgc->x = x;
+ pgc->y = y;
+ PGCLOG(("MOVE %x.%04x,%x.%04x\n", HWORD(x), LWORD(x), HWORD(y), LWORD(y)));
+}
+
+/* Set the 3D drawing position */
+static void hndl_move3(pgc_core_t *pgc)
+{
+ int32_t x = 0, y = 0, z = 0;
+
+ if (!pgc_param_coord(pgc, &x)) return;
+ if (!pgc_param_coord(pgc, &y)) return;
+ if (!pgc_param_coord(pgc, &z)) return;
+
+ pgc->x = x;
+ pgc->y = y;
+ pgc->z = z;
+}
+
+/* Relative move (2D) */
+static void hndl_mover(pgc_core_t *pgc)
+{
+ int32_t x = 0, y = 0;
+
+ if (!pgc_param_coord(pgc, &x)) return;
+ if (!pgc_param_coord(pgc, &y)) return;
+
+ pgc->x += x;
+ pgc->y += y;
+}
+
+/* Relative move (3D) */
+static void hndl_mover3(pgc_core_t *pgc)
+{
+ int32_t x = 0, y = 0, z = 0;
+
+ if (!pgc_param_coord(pgc, &x)) return;
+ if (!pgc_param_coord(pgc, &y)) return;
+ if (!pgc_param_coord(pgc, &z)) return;
+
+ pgc->x += x;
+ pgc->y += y;
+ pgc->z += z;
+}
+
+
+
+/* Draw a line (using PGC fixed-point coordinates) */
+uint16_t pgc_draw_line(pgc_core_t *pgc, int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint16_t linemask)
+{
+
+ PGCLOG(("pgc_draw_line: (%d,%d) to (%d,%d)\n", x0 >> 16, y0 >> 16,
+ x1 >> 16, y1 >> 16));
+ /* Convert from PGC fixed-point to device coordinates */
+ x0 >>= 16;
+ x1 >>= 16;
+ y0 >>= 16;
+ y1 >>= 16;
+
+ pgc_ito_raster(pgc, &x0, &y0);
+ pgc_ito_raster(pgc, &x1, &y1);
+
+ return pgc_draw_line_r(pgc, x0, y0, x1, y1, linemask);
+}
+
+/* Draw a line (using raster coordinates)
+ Bresenham's Algorithm from
+ *
+ * The line pattern mask to use is passed in. The return value is the line
+ * pattern mask rotated by the number of points drawn.
+ */
+uint16_t pgc_draw_line_r(pgc_core_t *pgc, int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint16_t linemask)
+{
+ int32_t dx, dy, sx, sy, err, e2;
+
+ dx = abs(x1 - x0);
+ dy = abs(y1 - y0);
+ sx = (x0 < x1) ? 1 : -1;
+ sy = (y0 < y1) ? 1 : -1;
+ err = (dx > dy ? dx : -dy) / 2;
+
+ for(;;)
+ {
+ if (linemask & 0x8000)
+ {
+ pgc_plot(pgc, x0, y0);
+ linemask = (linemask << 1) | 1;
+ }
+ else
+ {
+ linemask = (linemask << 1);
+ }
+ if (x0 == x1 && y0 == y1) break;
+ e2 = err;
+ if (e2 > -dx) { err -= dy; x0 += sx; }
+ if (e2 < dy) { err += dx; y0 += sy; }
+ }
+ return linemask;
+}
+
+/* Draw a horizontal line in the current fill pattern
+ * (using raster coordinates) */
+void pgc_fill_line_r(pgc_core_t *pgc, int32_t x0, int32_t x1, int32_t y0)
+{
+ int32_t x;
+ int32_t mask = 0x8000 >> (x0 & 0x0F);
+
+ if (x0 > x1) { x = x1; x1 = x0; x0 = x; }
+
+ for (x = x0; x <= x1; x++)
+ {
+ if (pgc->fill_pattern[y0 & 0x0F] & mask)
+ pgc_plot(pgc, x, y0);
+ mask = mask >> 1;
+ if (mask == 0) mask = 0x8000;
+ }
+}
+
+/* For sorting polygon nodes */
+static int compare_double(const void *a, const void *b)
+{
+ const double *da = (const double *)a;
+ const double *db = (const double *)b;
+
+ if (*da > *db) return 1;
+ if (*da < *db) return -1;
+ return 0;
+}
+
+/* Draw a filled polygon (using PGC fixed-point coordinates) */
+void pgc_fill_polygon(pgc_core_t *pgc,
+ unsigned corners, int32_t *x, int32_t *y)
+{
+ double *nodex;
+ double *dx;
+ double *dy;
+ unsigned n, nodes, i, j;
+ double ymin, ymax, ypos;
+
+ PGCLOG(("pgc_fill_polygon(%d corners)\n", corners));
+
+ if (corners < 2) return; /* Degenerate polygon */
+ nodex = malloc(corners * sizeof(double));
+ dx = malloc(corners * sizeof(double));
+ dy = malloc(corners * sizeof(double));
+ if (!nodex || !dx || !dy) return;
+
+ ymin = ymax = y[0] / 65536.0;
+ for (n = 0; n < corners; n++)
+ {
+ /* Convert from PGC fixed-point to native floating-point */
+ dx[n] = x[n] / 65536.0;
+ dy[n] = y[n] / 65536.0;
+
+ if (dy[n] < ymin) ymin = dy[n];
+ if (dy[n] > ymax) ymax = dy[n];
+ }
+ /* Polygon fill. Based on */
+ /* For each row, work out where the polygon lines intersect with
+ * that row. */
+ for (ypos = ymin; ypos <= ymax; ypos++)
+ {
+ nodes = 0;
+ j = corners - 1;
+ for (i = 0; i < corners; i++)
+ {
+ if ((dy[i] < ypos && dy[j] >= ypos)
+ || (dy[j] < ypos && dy[i] >= ypos)) /* Line crosses */
+ {
+ nodex[nodes++] = dx[i] + (ypos-dy[i])/(dy[j]-dy[i]) * (dx[j] - dx[i]);
+ }
+ j = i;
+ }
+
+ /* Sort the intersections */
+ if (nodes) qsort(nodex, nodes, sizeof(double), compare_double);
+/*
+ PGCLOG(("pgc_fill_polygon ypos=%f nodes=%d ", ypos, nodes));
+ for (i = 0; i < nodes; i++)
+ {
+ PGCLOG(("%f;", nodex[i]));
+ }
+ PGCLOG(("\n"));
+*/
+ /* And fill between them */
+ for (i = 0; i < nodes; i += 2)
+ {
+ int16_t x1 = nodex[i], x2 = nodex[i + 1],
+ y1 = ypos, y2 = ypos;
+ pgc_sto_raster(pgc, &x1, &y1);
+ pgc_sto_raster(pgc, &x2, &y2);
+/* PGCLOG(("pgc_fill_polygon raster %d,%d to %d,%d\n",
+ x1, y1, x2, y2)); */
+ pgc_fill_line_r(pgc, x1, x2, y1);
+ }
+ }
+ free(nodex);
+ free(dx);
+ free(dy);
+}
+
+
+
+/* Draw a filled ellipse (using PGC fixed-point coordinates) */
+void pgc_draw_ellipse(pgc_core_t *pgc, int32_t x, int32_t y)
+{
+ /* Convert from PGC fixed-point to native floating-point */
+ double h = y / 65536.0;
+ double w = x / 65536.0;
+ double y0 = pgc->y / 65536.0;
+ double x0 = pgc->x / 65536.0;
+ double ypos = 0.0, xpos = 0.0;
+ double x1;
+ double xlast = 0.0;
+ int16_t linemask = pgc->line_pattern;
+
+ pgc_dto_raster(pgc, &x0, &y0);
+ PGCLOG(("Ellipse: Colour=%d Drawmode=%d fill=%d\n", pgc->colour,
+ pgc->draw_mode, pgc->fill_mode));
+ for (ypos = 0; ypos <= h; ypos++)
+ {
+ if (ypos == 0)
+ {
+ if (pgc->fill_mode)
+ {
+ pgc_fill_line_r(pgc, x0 - w, x0 + w, y0);
+ }
+ if (linemask & 0x8000)
+ {
+ pgc_plot(pgc, x0 + w, y0);
+ pgc_plot(pgc, x0 - w, y0);
+ linemask = (linemask << 1) | 1;
+ }
+ else
+ {
+ linemask = linemask << 1;
+ }
+ xlast = w;
+ }
+ else
+ {
+ x1 = sqrt((h * h) - (ypos * ypos)) * w / h;
+
+ if (pgc->fill_mode)
+ {
+ pgc_fill_line_r(pgc, x0 - x1, x0 + x1, y0 + ypos);
+ pgc_fill_line_r(pgc, x0 - x1, x0 + x1, y0 - ypos);
+ }
+
+ /* Draw border */
+ for (xpos = xlast; xpos >= x1; xpos--)
+ {
+ if (linemask & 0x8000)
+ {
+ pgc_plot(pgc, x0 + xpos, y0 + ypos);
+ pgc_plot(pgc, x0 - xpos, y0 + ypos);
+ pgc_plot(pgc, x0 + xpos, y0 - ypos);
+ pgc_plot(pgc, x0 - xpos, y0 - ypos);
+ linemask = (linemask << 1) | 1;
+ }
+ else
+ {
+ linemask = linemask << 1;
+ }
+
+ }
+ xlast = x1;
+ }
+ }
+}
+
+/* Handle the ELIPSE (sic) command */
+static void hndl_ellipse(pgc_core_t *pgc)
+{
+ int32_t x = 0, y = 0;
+
+ if (!pgc_param_coord(pgc, &x)) return;
+ if (!pgc_param_coord(pgc, &y)) return;
+
+ pgc_draw_ellipse(pgc, x, y);
+}
+
+
+
+
+/* Handle the POLY command */
+static void hndl_poly(pgc_core_t *pgc)
+{
+ uint8_t count;
+ int32_t x[256];
+ int32_t y[256];
+ int32_t n;
+
+ if (!pgc_param_byte(pgc, &count)) return;
+
+ for (n = 0; n < count; n++)
+ {
+ if (!pgc_param_coord(pgc, &x[n])) return;
+ if (!pgc_param_coord(pgc, &y[n])) return;
+ }
+ PGCLOG(("POLY (%d)\n", count));
+}
+
+/* Parse but don't execute a POLY command (for adding to a command list) */
+static int parse_poly(pgc_core_t *pgc, pgc_commandlist_t *cl, int c)
+{
+ uint8_t count;
+
+ PGCLOG(("parse_poly\n"));
+ if (!pgc_param_byte(pgc, &count)) return 0;
+ PGCLOG(("parse_poly: count=%02x\n", count));
+
+ if (!pgc_commandlist_append(cl, count))
+ {
+ pgc_error(pgc, PGC_ERROR_OVERFLOW);
+ return 0;
+ }
+ PGCLOG(("parse_poly: parse %d coords\n", 2 * count));
+ return pgc_parse_coords(pgc, cl, 2 * count);
+}
+
+
+/* Parse but don't execute a command with a fixed number of byte parameters */
+int pgc_parse_bytes(pgc_core_t *pgc, pgc_commandlist_t *cl, int count)
+{
+ uint8_t *param = malloc(count);
+ int n;
+
+ if (!param)
+ {
+ pgc_error(pgc, PGC_ERROR_OVERFLOW);
+ return 0;
+ }
+ for (n = 0; n < count; n++)
+ {
+ if (!pgc_param_byte(pgc, ¶m[n]))
+ {
+ free(param);
+ return 0;
+ }
+ }
+ for (n = 0; n < count; n++)
+ {
+ if (!pgc_commandlist_append(cl, param[n]))
+ {
+ pgc_error(pgc, PGC_ERROR_OVERFLOW);
+ free(param);
+ return 0;
+ }
+ }
+ free(param);
+ return 1;
+}
+
+
+/* Parse but don't execute a command with a fixed number of word parameters */
+int pgc_parse_words(pgc_core_t *pgc, pgc_commandlist_t *cl, int count)
+{
+ int16_t *param = malloc(count * sizeof(int16_t));
+ int n;
+
+ if (!param)
+ {
+ pgc_error(pgc, PGC_ERROR_OVERFLOW);
+ return 0;
+ }
+ for (n = 0; n < count; n++)
+ {
+ if (!pgc_param_word(pgc, ¶m[n])) return 0;
+ }
+ for (n = 0; n < count; n++)
+ {
+ if (!pgc_commandlist_append(cl, param[n] & 0xFF) ||
+ !pgc_commandlist_append(cl, param[n] >> 8))
+ {
+ pgc_error(pgc, PGC_ERROR_OVERFLOW);
+ free(param);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+
+/* Parse but don't execute a command with a fixed number of coord parameters */
+int pgc_parse_coords(pgc_core_t *pgc, pgc_commandlist_t *cl, int count)
+{
+ int32_t *param = malloc(count * sizeof(int32_t));
+ int n;
+
+ if (!param)
+ {
+ pgc_error(pgc, PGC_ERROR_OVERFLOW);
+ return 0;
+ }
+ for (n = 0; n < count; n++)
+ {
+ if (!pgc_param_coord(pgc, ¶m[n])) return 0;
+ }
+/* Here's how the real PGC serialises coords:
+ *
+ * 100.5 -> 64 00 00 80 ie 0064.8000
+ * 100.3 -> 64 00 CD 4C ie 0064.4CCD
+ *
+ */
+ for (n = 0; n < count; n++)
+ {
+ /* Serialise integer part */
+ if (!pgc_commandlist_append(cl, (param[n] >> 16) & 0xFF) ||
+ !pgc_commandlist_append(cl, (param[n] >> 24) & 0xFF) ||
+ /* Serialise fraction part */
+ !pgc_commandlist_append(cl, (param[n] ) & 0xFF) ||
+ !pgc_commandlist_append(cl, (param[n] >> 8) & 0xFF))
+ {
+ pgc_error(pgc, PGC_ERROR_OVERFLOW);
+ free(param);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+
+/* Handle the DISPLAY command */
+static void hndl_display(pgc_core_t *pgc)
+{
+ uint8_t param;
+
+ if (!pgc_param_byte(pgc, ¶m)) return;
+
+ PGCLOG(("DISPLAY(%d)\n", param));
+ if (param > 1)
+ {
+ pgc_error(pgc, PGC_ERROR_RANGE);
+ }
+ else
+ {
+ pgc_setdisplay(pgc, param);
+ }
+}
+
+
+/* Handle the IMAGEW command (memory to screen blit) */
+static void hndl_imagew(pgc_core_t *pgc)
+{
+ int16_t row, col1, col2;
+ uint8_t v1, v2;
+
+ if (!pgc_param_word(pgc, &row)) return;
+ if (!pgc_param_word(pgc, &col1)) return;
+ if (!pgc_param_word(pgc, &col2)) return;
+
+ if (row >= pgc->screenh || col1 >= pgc->maxw || col2 >= pgc->maxw)
+ {
+ pgc_error(pgc, PGC_ERROR_RANGE);
+ return;
+ }
+
+ /* In ASCII mode, what is written is a stream of bytes */
+ if (pgc->ascii_mode)
+ {
+ while (col1 <= col2)
+ {
+ if (!pgc_param_byte(pgc, &v1)) return;
+ pgc_write_pixel(pgc, col1, row, v1);
+ ++col1;
+ }
+ return;
+ }
+ else /* In hex mode, it's RLE compressed */
+ {
+ while (col1 <= col2)
+ {
+ if (!pgc_param_byte(pgc, &v1)) return;
+
+ if (v1 & 0x80) /* Literal run */
+ {
+ v1 -= 0x7F;
+ while (col1 <= col2 && v1 != 0)
+ {
+ if (!pgc_param_byte(pgc, &v2)) return;
+ pgc_write_pixel(pgc, col1, row, v2);
+ ++col1;
+ --v1;
+ }
+ }
+ else /* Repeated run */
+ {
+ if (!pgc_param_byte(pgc, &v2)) return;
+
+ ++v1;
+ while (col1 <= col2 && v1 != 0)
+ {
+ pgc_write_pixel(pgc, col1, row, v2);
+ ++col1;
+ --v1;
+ }
+ }
+ }
+ }
+}
+
+
+/* Select one of the built-in palettes */
+static void pgc_init_lut(pgc_core_t *pgc, int param)
+{
+ if (param >= 0 && param < 6)
+ {
+ memcpy(pgc->palette, init_palette[param], sizeof(pgc->palette));
+ }
+ else if (param == 0xFF)
+ {
+ memcpy(pgc->palette, pgc->userpal, sizeof(pgc->palette));
+ }
+ else
+ {
+ pgc_error(pgc, PGC_ERROR_RANGE);
+ }
+}
+
+/* Save the current palette */
+static void hndl_lutsav(pgc_core_t *pgc)
+{
+ memcpy(pgc->userpal, pgc->palette, sizeof(pgc->palette));
+}
+
+
+/* Handle LUTINT (select palette) */
+static void hndl_lutint(pgc_core_t *pgc)
+{
+ uint8_t param;
+
+ if (!pgc_param_byte(pgc, ¶m)) return;
+
+ pgc_init_lut(pgc, param);
+}
+
+
+/* Handle LUTRD (read palette register) */
+static void hndl_lutrd(pgc_core_t *pgc)
+{
+ uint8_t param;
+ uint32_t col;
+
+ if (!pgc_param_byte(pgc, ¶m)) return;
+
+ col = pgc->palette[param];
+
+ pgc_result_byte(pgc, (col >> 20) & 0x0F);
+ pgc_result_byte(pgc, (col >> 12) & 0x0F);
+ pgc_result_byte(pgc, (col >> 4) & 0x0F);
+}
+
+/* Handle LUT (write palette register) */
+static void hndl_lut(pgc_core_t *pgc)
+{
+ uint8_t param[4];
+ int n;
+
+ for (n = 0; n < 4; n++)
+ {
+ if (!pgc_param_byte(pgc, ¶m[n])) return;
+ if (n > 0 && param[n] > 15)
+ {
+ pgc_error(pgc, PGC_ERROR_RANGE);
+ param[n] &= 0x0F;
+ }
+ }
+ pgc->palette[param[0]] = makecol((param[1] * 0x11),
+ (param[2] * 0x11),
+ (param[3] * 0x11));
+}
+
+/* LUT8RD and LUT8 are extensions implemented by several PGC clones, so
+ * here are functions that implement them even though they aren't
+ * used by the PGC */
+void pgc_hndl_lut8rd(pgc_core_t *pgc)
+{
+ uint8_t param;
+ uint32_t col;
+
+ if (!pgc_param_byte(pgc, ¶m)) return;
+
+ col = pgc->palette[param];
+
+ pgc_result_byte(pgc, (col >> 16) & 0xFF);
+ pgc_result_byte(pgc, (col >> 8) & 0xFF);
+ pgc_result_byte(pgc, col & 0xFF);
+}
+
+void pgc_hndl_lut8(pgc_core_t *pgc)
+{
+ uint8_t param[4];
+ int n;
+
+ for (n = 0; n < 4; n++)
+ {
+ if (!pgc_param_byte(pgc, ¶m[n])) return;
+ }
+ pgc->palette[param[0]] = makecol((param[1]), (param[2]), (param[3]));
+}
+
+
+/* Handle AREAPT (set 16x16 fill pattern) */
+static void hndl_areapt(pgc_core_t *pgc)
+{
+ int16_t pattern[16];
+ int n;
+
+ for (n = 0; n < 16; n++)
+ {
+ if (!pgc_param_word(pgc, &pattern[n])) return;
+ }
+ memcpy(pgc->fill_pattern, pattern, sizeof(pgc->fill_pattern));
+ PGCLOG(("AREAPT(%04x %04x %04x %04x...)\n",
+ pattern[0] & 0xFFFF, pattern[1] & 0xFFFF,
+ pattern[2] & 0xFFFF, pattern[3] & 0xFFFF));
+}
+
+
+/* Handle CA (select ASCII mode) */
+static void hndl_ca(pgc_core_t *pgc)
+{
+ pgc->ascii_mode = 1;
+}
+
+/* Handle CX (select hex mode) */
+static void hndl_cx(pgc_core_t *pgc)
+{
+ pgc->ascii_mode = 0;
+}
+
+/* CA and CX remain valid in hex mode; they are handled as command 0x43 ('C')
+ * with a one-byte parameter */
+static void hndl_c(pgc_core_t *pgc)
+{
+ uint8_t param;
+
+ if (!pgc->inputbyte(pgc, ¶m)) return;
+
+ if (param == 'A') pgc->ascii_mode = 1;
+ if (param == 'X') pgc->ascii_mode = 0;
+}
+
+/* RESETF resets the PGC */
+static void hndl_resetf(pgc_core_t *pgc)
+{
+ pgc_reset(pgc);
+}
+
+
+
+/* TJUST sets text justify settings */
+static void hndl_tjust(pgc_core_t *pgc)
+{
+ uint8_t param[2];
+
+ if (!pgc->inputbyte(pgc, ¶m[0])) return;
+ if (!pgc->inputbyte(pgc, ¶m[1])) return;
+
+ if (param[0] >= 1 && param[0] <= 3 &&
+ param[1] >= 1 && param[1] <= 3)
+ {
+ pgc->tjust_h = param[0];
+ pgc->tjust_v = param[1];
+ }
+ else
+ {
+ pgc_error(pgc, PGC_ERROR_RANGE);
+ }
+}
+
+/* TSIZE controls text horizontal spacing */
+static void hndl_tsize(pgc_core_t *pgc)
+{
+ int32_t param = 0;
+
+ if (!pgc_param_coord(pgc, ¶m)) return;
+
+ pgc->tsize = param;
+ PGCLOG(("TSIZE %d\n", param));
+}
+
+
+/* VWPORT sets up the viewport (roughly, the clip rectangle) in raster
+ * coordinates, measured from the bottom left of the screen */
+static void hndl_vwport(pgc_core_t *pgc)
+{
+ int16_t x1, x2, y1, y2;
+
+ if (!pgc_param_word(pgc, &x1)) return;
+ if (!pgc_param_word(pgc, &x2)) return;
+ if (!pgc_param_word(pgc, &y1)) return;
+ if (!pgc_param_word(pgc, &y2)) return;
+
+ PGCLOG(("VWPORT %d,%d,%d,%d\n", x1,x2,y1,y2));
+ pgc->vp_x1 = x1;
+ pgc->vp_x2 = x2;
+ pgc->vp_y1 = y1;
+ pgc->vp_y2 = y2;
+}
+
+/* WINDOW defines the coordinate system in use */
+static void hndl_window(pgc_core_t *pgc)
+{
+ int16_t x1, x2, y1, y2;
+
+ if (!pgc_param_word(pgc, &x1)) return;
+ if (!pgc_param_word(pgc, &x2)) return;
+ if (!pgc_param_word(pgc, &y1)) return;
+ if (!pgc_param_word(pgc, &y2)) return;
+
+ PGCLOG(("WINDOW %d,%d,%d,%d\n", x1,x2,y1,y2));
+ pgc->win_x1 = x1;
+ pgc->win_x2 = x2;
+ pgc->win_y1 = y1;
+ pgc->win_y2 = y2;
+}
+
+
+
+/* The list of commands implemented by this mini-PGC. In order to support
+ * the original PGC and clones, we support two lists; core commands (listed
+ * below) and subclass commands (listed in the clone).
+ *
+ * Each row has five parameters:
+ * ASCII-mode command
+ * Hex-mode command
+ * Function that executes this command
+ * Function that parses this command when building a command list
+ * Parameter for the parse function
+ *
+ * TODO: This list omits numerous commands present in a genuine PGC
+ * (ARC, AREA, AREABC, BUFFER, CIRCLE etc etc).
+ * TODO: Some commands don't have a parse function (for example, IMAGEW)
+ *
+ * The following ASCII entries have special meaning:
+ * ~~~~~~ command is valid only in hex mode
+ * ****** end of subclass command list, now process core command list
+ * @@@@@@ end of core command list
+ *
+ */
+static const pgc_command_t pgc_core_commands[] =
+{
+ { "AREAPT", 0xE7, hndl_areapt, pgc_parse_words, 16 },
+ { "AP", 0xE7, hndl_areapt, pgc_parse_words, 16 },
+ { "~~~~~~", 0x43, hndl_c }, /* Handle CA / CX in hex mode */
+ { "CA", 0xD2, hndl_ca },
+ { "CLBEG", 0x70, hndl_clbeg },
+ { "CB", 0x70, hndl_clbeg },
+ { "CLDEL", 0x74, hndl_cldel, pgc_parse_bytes, 1 },
+ { "CD", 0x74, hndl_cldel, pgc_parse_bytes, 1 },
+ { "CLEND", 0x71, hndl_clend },
+ { "CLRUN", 0x72, hndl_clrun, pgc_parse_bytes, 1 },
+ { "CR", 0x72, hndl_clrun, pgc_parse_bytes, 1 },
+ { "CLRD", 0x75, hndl_clread, pgc_parse_bytes, 1 },
+ { "CRD", 0x75, hndl_clread, pgc_parse_bytes, 1 },
+ { "CLOOP", 0x73, hndl_cloop },
+ { "CL", 0x73, hndl_cloop },
+ { "CLEARS", 0x0F, hndl_clears, pgc_parse_bytes, 1 },
+ { "CLS", 0x0F, hndl_clears, pgc_parse_bytes, 1 },
+ { "COLOR", 0x06, hndl_color, pgc_parse_bytes, 1 },
+ { "C", 0x06, hndl_color, pgc_parse_bytes, 1 },
+ { "CX", 0xD1, hndl_cx },
+ { "DISPLA", 0xD0, hndl_display, pgc_parse_bytes, 1 },
+ { "DI", 0xD0, hndl_display, pgc_parse_bytes, 1 },
+ { "ELIPSE", 0x39, hndl_ellipse, pgc_parse_coords, 2 },
+ { "EL", 0x39, hndl_ellipse, pgc_parse_coords, 2 },
+ { "IMAGEW", 0xD9, hndl_imagew },
+ { "IW", 0xD9, hndl_imagew },
+ { "LINFUN", 0xEB, hndl_linfun, pgc_parse_bytes, 1 },
+ { "LF", 0xEB, hndl_linfun, pgc_parse_bytes, 1 },
+ { "LINPAT", 0xEA, hndl_linpat, pgc_parse_words, 1 },
+ { "LP", 0xEA, hndl_linpat, pgc_parse_words, 1 },
+ { "LUTINT", 0xEC, hndl_lutint, pgc_parse_bytes, 1 },
+ { "LI", 0xEC, hndl_lutint, pgc_parse_bytes, 1 },
+ { "LUTRD", 0x50, hndl_lutrd, pgc_parse_bytes, 1 },
+ { "LUTSAV", 0xED, hndl_lutsav, NULL, 0 },
+ { "LUT", 0xEE, hndl_lut, pgc_parse_bytes, 4 },
+ { "MOVE", 0x10, hndl_move, pgc_parse_coords, 2 },
+ { "M", 0x10, hndl_move, pgc_parse_coords, 2 },
+ { "MOVE3", 0x12, hndl_move3, pgc_parse_coords, 3 },
+ { "M3", 0x12, hndl_move3, pgc_parse_coords, 3 },
+ { "MOVER", 0x11, hndl_mover, pgc_parse_coords, 2 },
+ { "MR", 0x11, hndl_mover, pgc_parse_coords, 2 },
+ { "MOVER3", 0x13, hndl_mover3, pgc_parse_coords, 3 },
+ { "MR3", 0x13, hndl_mover3, pgc_parse_coords, 3 },
+ { "PRMFIL", 0xE9, hndl_prmfil, pgc_parse_bytes, 1 },
+ { "PF", 0xE9, hndl_prmfil, pgc_parse_bytes, 1 },
+ { "POLY", 0x30, hndl_poly, parse_poly },
+ { "P", 0x30, hndl_poly, parse_poly },
+ { "RESETF", 0x04, hndl_resetf, NULL, 0 },
+ { "RF", 0x04, hndl_resetf, NULL, 0 },
+ { "TJUST", 0x85, hndl_tjust, pgc_parse_bytes, 2 },
+ { "TJ", 0x85, hndl_tjust, pgc_parse_bytes, 2 },
+ { "TSIZE", 0x81, hndl_tsize, pgc_parse_coords, 1 },
+ { "TS", 0x81, hndl_tsize, pgc_parse_coords, 1 },
+ { "VWPORT", 0xB2, hndl_vwport, pgc_parse_words, 4 },
+ { "VWP", 0xB2, hndl_vwport, pgc_parse_words, 4 },
+ { "WINDOW", 0xB3, hndl_window, pgc_parse_words, 4 },
+ { "WI", 0xB3, hndl_window, pgc_parse_words, 4 },
+
+ { "@@@@@@", 0x00, NULL }
+};
+
+
+/* Writes to CGA registers are copied into the transfer memory buffer */
+void pgc_out(uint16_t addr, uint8_t val, void *p)
+{
+ pgc_core_t *pgc = (pgc_core_t *)p;
+
+ switch(addr)
+ {
+ case 0x3D0: case 0x3D2: case 0x3D4: case 0x3D6:
+ pgc->mapram[0x3D0] = val; break;
+ case 0x3D1: case 0x3D3: case 0x3D5: case 0x3D7:
+ if (pgc->mapram[0x3D0] < 18)
+ {
+ pgc->mapram[0x3E0 + pgc->mapram[0x3D0]] = val;
+ }
+ break;
+ case 0x3D8: pgc->mapram[0x3D8] = val; break;
+ case 0x3D9: pgc->mapram[0x3D9] = val; break;
+ }
+
+}
+
+/* Read back the CGA registers */
+uint8_t pgc_in(uint16_t addr, void *p)
+{
+ pgc_core_t *pgc = (pgc_core_t *)p;
+
+ switch(addr)
+ {
+ case 0x3D0: case 0x3D2: case 0x3D4: case 0x3D6:
+ return pgc->mapram[0x3D0];
+ case 0x3D1: case 0x3D3: case 0x3D5: case 0x3D7:
+ if (pgc->mapram[0x3D0] < 18)
+ {
+ return pgc->mapram[0x3E0 + pgc->mapram[0x3D0]];
+ }
+ return 0xFF;
+
+ case 0x3D8: return pgc->mapram[0x3D8];
+ case 0x3D9: return pgc->mapram[0x3D9];
+ case 0x3DA: return pgc->mapram[0x3DA];
+ }
+ return 0xFF;
+}
+
+/* Memory write to the transfer buffer */
+void pgc_write(uint32_t addr, uint8_t val, void *p)
+{
+ pgc_core_t *pgc = (pgc_core_t *)p;
+
+ /* It seems variable whether the PGC maps 1k or 2k at 0xC6000.
+ * Map 2k here in case a clone requires it */
+ if (addr >= 0xC6000 && addr < 0xC6800)
+ {
+ addr &= 0x7FF;
+
+ /* If one of the FIFOs has been updated, this may cause
+ * the drawing thread to be woken */
+
+ if (pgc->mapram[addr] != val)
+ {
+ pgc->mapram[addr] = val;
+ switch (addr)
+ {
+ case 0x300: /* Input write pointer */
+ if (pgc->waiting_input_fifo &&
+ pgc->mapram[0x300] != pgc->mapram[0x301])
+ {
+ pgc->waiting_input_fifo = 0;
+ pgc_wake(pgc);
+ }
+ break;
+
+ case 0x303: /* Output read pointer */
+ if (pgc->waiting_output_fifo &&
+ pgc->mapram[0x302] != (uint8_t)(pgc->mapram[0x303] - 1))
+ {
+ pgc->waiting_output_fifo = 0;
+ pgc_wake(pgc);
+ }
+ break;
+
+ case 0x305: /* Error read pointer */
+ if (pgc->waiting_error_fifo &&
+ pgc->mapram[0x304] != (uint8_t)(pgc->mapram[0x305] - 1))
+ {
+ pgc->waiting_error_fifo = 0;
+ pgc_wake(pgc);
+ }
+ break;
+
+ case 0x306: /* Cold start flag */
+ /* XXX This should be in IM-1024 specific code */
+ pgc->mapram[0x306] = 0;
+ break;
+
+ case 0x030C: /* Display type */
+ pgc_setdisplay(p, pgc->mapram[0x30C]);
+ pgc->mapram[0x30D] = pgc->mapram[0x30C];
+ break;
+
+
+ case 0x3FF: /* Reboot the PGC
+ (handled on core thread) */
+ pgc_wake(pgc);
+ break;
+ } // end switch (addr)
+ }
+ }
+ if (addr >= 0xB8000 && addr < 0xBC000 && pgc->cga_selected)
+ {
+ addr &= 0x3FFF;
+ pgc->cga_vram[addr] = val;
+ }
+}
+
+
+uint8_t pgc_read(uint32_t addr, void *p)
+{
+ pgc_core_t *pgc = (pgc_core_t *)p;
+
+ if (addr >= 0xC6000 && addr < 0xC6800)
+ {
+ addr &= 0x7FF;
+
+ return pgc->mapram[addr];
+ }
+ if (addr >= 0xB8000 && addr < 0xBC000 && pgc->cga_selected)
+ {
+ addr &= 0x3FFF;
+ return pgc->cga_vram[addr];
+ }
+ return 0xFF;
+}
+
+/* Called by the drawing thread to read the next byte from the input
+ * buffer. If no byte available will sleep until one is. Returns 0 if
+ * a PGC reset has been triggered by a write to 0xC63FF */
+int pgc_input_byte(pgc_core_t *pgc, uint8_t *result)
+{
+ /* If input buffer empty, wait for it to fill */
+ while (pgc->mapram[0x300] == pgc->mapram[0x301])
+ {
+ pgc->waiting_input_fifo = 1;
+ pgc_sleep(pgc);
+ }
+ if (pgc->mapram[0x3FF]) /* Reset triggered */
+ {
+ pgc_reset(pgc);
+ return 0;
+ }
+
+ *result = pgc->mapram[pgc->mapram[0x301]];
+ ++pgc->mapram[0x301];
+ return 1;
+}
+
+/* Called by the drawing thread to write a byte to the output buffer.
+ * If buffer is full will sleep until it is not. Returns 0 if
+ * a PGC reset has been triggered by a write to 0xC63FF */
+int pgc_output_byte(pgc_core_t *pgc, uint8_t val)
+{
+ /* If output buffer full, wait for it to empty */
+ while (pgc->mapram[0x302] == (uint8_t)(pgc->mapram[0x303] - 1))
+ {
+ PGCLOG(("Output buffer state: %02x %02x Sleeping\n",
+ pgc->mapram[0x302], pgc->mapram[0x303]));
+ pgc->waiting_output_fifo = 1;
+ pgc_sleep(pgc);
+ }
+ if (pgc->mapram[0x3FF]) /* Reset triggered */
+ {
+ pgc_reset(pgc);
+ return 0;
+ }
+ pgc->mapram[0x100 + pgc->mapram[0x302]] = val;
+ ++pgc->mapram[0x302];
+/*
+ PGCLOG(("Output %02x: new state: %02x %02x\n", val,
+ pgc->mapram[0x302], pgc->mapram[0x303])); */
+ return 1;
+}
+
+/* Helper to write an entire string to the output buffer */
+int pgc_output_string(pgc_core_t *pgc, const char *s)
+{
+ while (*s)
+ {
+ if (!pgc_output_byte(pgc, *s)) return 0;
+ ++s;
+ }
+ return 1;
+}
+
+/* As pgc_output_byte, for the error buffer */
+int pgc_error_byte(pgc_core_t *pgc, uint8_t val)
+{
+ /* If error buffer full, wait for it to empty */
+ while (pgc->mapram[0x304] == pgc->mapram[0x305] - 1)
+ {
+ pgc->waiting_error_fifo = 1;
+ pgc_sleep(pgc);
+ }
+ if (pgc->mapram[0x3FF]) /* Reset triggered */
+ {
+ pgc_reset(pgc);
+ return 0;
+ }
+ pgc->mapram[0x200 + pgc->mapram[0x304]] = val;
+ ++pgc->mapram[0x304];
+ return 1;
+}
+
+/* As pgc_output_string, for the error buffer */
+int pgc_error_string(pgc_core_t *pgc, const char *s)
+{
+ while (*s)
+ {
+ if (!pgc_error_byte(pgc, *s)) return 0;
+ ++s;
+ }
+ return 1;
+}
+
+
+/* Report an error, either in ASCII or in hex */
+int pgc_error(pgc_core_t *pgc, int err)
+{
+ if (pgc->mapram[0x307]) /* Errors enabled? */
+ {
+ if (pgc->ascii_mode)
+ {
+ if (err >= PGC_ERROR_RANGE && err <= PGC_ERROR_MISSING)
+ return pgc_error_string(pgc, pgc_err_msgs[err]);
+ return pgc_error_string(pgc, "Unknown error\r");
+ }
+ else
+ {
+ return pgc_error_byte(pgc, err);
+ }
+ }
+ return 1;
+}
+
+
+static inline int is_whitespace(char ch)
+{
+ return (ch != 0 && strchr(" \r\n\t,;()+-", ch) != NULL);
+}
+
+
+/* Read a byte and interpret as ASCII: ignore control characters other than
+ * CR, LF or tab. */
+int pgc_input_char(pgc_core_t *pgc, char *result)
+{
+ uint8_t ch;
+
+ while (1)
+ {
+ if (!pgc->inputbyte(pgc, &ch)) return 0;
+
+ ch &= 0x7F;
+ if (ch == '\r' || ch == '\n' || ch == '\t' || ch >= ' ')
+ {
+ *result = toupper(ch);
+ return 1;
+ }
+ }
+}
+
+
+/* Parameter passed is not a number: abort */
+static int err_digit(pgc_core_t *pgc)
+{
+ uint8_t asc;
+
+ do /* Swallow everything until the next separator */
+ {
+ if (!pgc->inputbyte(pgc, &asc)) return 0;
+ }
+ while (!is_whitespace(asc));
+ pgc_error(pgc, PGC_ERROR_DIGIT);
+ return 0;
+}
+
+
+typedef enum parse_state_t
+{
+ PS_MAIN,
+ PS_FRACTION,
+ PS_EXPONENT
+} parse_state_t;
+
+/* Read in a PGC coordinate, either as hex (4 bytes) or ASCII (xxxx.yyyyEeee)
+ * Returns 0 if PGC reset detected while the value is being read */
+int pgc_param_coord(pgc_core_t *pgc, int32_t *value)
+{
+ uint8_t asc;
+ int sign = 1;
+ int esign = 1;
+ int n;
+ uint16_t dp = 1;
+ uint16_t integer = 0;
+ uint16_t frac = 0;
+ uint16_t exponent = 0;
+ uint32_t res;
+ parse_state_t state = PS_MAIN;
+ uint8_t encoded[4];
+
+ /* If there is a command list running, pull the bytes out of that
+ * command list */
+ if (pgc->clcur)
+ {
+ for (n = 0; n < 4; n++)
+ {
+ if (!pgc_clist_byte(pgc, &encoded[n])) return 0;
+ }
+ integer = (((int16_t)encoded[1]) << 8) | encoded[0];
+ frac = (((int16_t)encoded[3]) << 8) | encoded[2];
+
+ *value = (((int32_t)integer) << 16) | frac;
+ return 1;
+ }
+ /* If in hex mode, read in the encoded integer and fraction parts
+ * from the hex stream */
+ if (!pgc->ascii_mode)
+ {
+ for (n = 0; n < 4; n++)
+ {
+ if (!pgc->inputbyte(pgc, &encoded[n])) return 0;
+ }
+ integer = (((int16_t)encoded[1]) << 8) | encoded[0];
+ frac = (((int16_t)encoded[3]) << 8) | encoded[2];
+
+ *value = (((int32_t)integer) << 16) | frac;
+ return 1;
+ }
+ /* Parsing an ASCII value */
+
+ /* Skip separators */
+ do
+ {
+ if (!pgc->inputbyte(pgc, &asc)) return 0;
+ if (asc == '-') sign = -1;
+ }
+ while (is_whitespace(asc));
+
+ /* There had better be a digit next */
+ if (!isdigit(asc))
+ {
+ pgc_error(pgc, PGC_ERROR_MISSING);
+ return 0;
+ }
+ do
+ {
+ switch (asc)
+ {
+/* Decimal point is acceptable in 'main' state (start of fraction)
+ * not otherwise */
+ case '.':
+ if (state == PS_MAIN)
+ {
+ if (!pgc->inputbyte(pgc, &asc)) return 0;
+ state = PS_FRACTION;
+ continue;
+ }
+ else
+ {
+ pgc_error(pgc, PGC_ERROR_MISSING);
+ return err_digit(pgc);
+ }
+ break;
+ /* Scientific notation */
+ case 'd': case 'D': case 'e': case 'E':
+ esign = 1;
+ if (!pgc->inputbyte(pgc, &asc)) return 0;
+ if (asc == '-')
+ {
+ sign = -1;
+ if (!pgc->inputbyte(pgc, &asc)) return 0;
+ }
+ state = PS_EXPONENT;
+ continue;
+ /* Should be a number or a separator */
+ default:
+ if (is_whitespace(asc)) break;
+ if (!isdigit(asc))
+ {
+ pgc_error(pgc, PGC_ERROR_MISSING);
+ return err_digit(pgc);
+ }
+ asc -= '0'; /* asc is digit */
+ switch (state)
+ {
+ case PS_MAIN:
+ integer = (integer * 10)+asc;
+ if (integer & 0x8000) /* Overflow */
+ {
+ pgc_error(pgc, PGC_ERROR_RANGE);
+ integer = 0x7FFF;
+ }
+ break;
+ case PS_FRACTION:
+ frac = (frac * 10)+asc;
+ dp *= 10;
+ break;
+ case PS_EXPONENT:
+ exponent = (exponent * 10)+asc;
+ break;
+ }
+
+ }
+ if (!pgc->inputbyte(pgc, &asc)) return 0;
+ }
+ while (!is_whitespace(asc));
+
+
+ res = (frac << 16) / dp;
+ PGCLOG(("integer=%u frac=%u exponent=%u dp=%d res=0x%08x\n",
+ integer, frac, exponent, dp, res));
+
+ res = (res & 0xFFFF) | (integer << 16);
+ if (exponent)
+ {
+ for (n = 0; n < exponent; n++)
+ {
+ if (esign > 0) res *= 10;
+ else res /= 10;
+ }
+ }
+ *value = sign*res;
+
+ return 1;
+}
+
+/* Pull the next byte from the current command list */
+int pgc_clist_byte(pgc_core_t *pgc, uint8_t *val)
+{
+ if (pgc->clcur == NULL) return 0;
+
+ if (pgc->clcur->rdptr < pgc->clcur->wrptr)
+ {
+ *val = pgc->clcur->list[pgc->clcur->rdptr++];
+ }
+ else
+ {
+ *val = 0;
+ }
+ /* If we've reached the end, reset to the beginning and
+ * (if repeating) run the repeat */
+ if (pgc->clcur->rdptr >= pgc->clcur->wrptr)
+ {
+ pgc->clcur->rdptr = 0;
+ --pgc->clcur->repeat;
+ if (pgc->clcur->repeat == 0)
+ {
+ pgc->clcur = pgc->clcur->chain;
+ }
+ }
+ return 1;
+}
+
+
+/* Read in a byte, either as hex (1 byte) or ASCII (decimal).
+ * Returns 0 if PGC reset detected while the value is being read */
+int pgc_param_byte(pgc_core_t *pgc, uint8_t *val)
+{
+ int32_t c;
+
+ if (pgc->clcur) return pgc_clist_byte(pgc, val);
+
+ if (!pgc->ascii_mode) return pgc->inputbyte(pgc, val);
+
+ if (!pgc_param_coord(pgc, &c)) return 0;
+ c = (c >> 16); /* Drop fractional part */
+
+ if (c > 255)
+ {
+ pgc_error(pgc, PGC_ERROR_RANGE);
+ return 0;
+ }
+ *val = (uint8_t)c;
+ return 1;
+}
+
+/* Read in a word, either as hex (2 bytes) or ASCII (decimal).
+ * Returns 0 if PGC reset detected while the value is being read */
+int pgc_param_word(pgc_core_t *pgc, int16_t *val)
+{
+ int32_t c;
+
+ if (pgc->clcur)
+ {
+ uint8_t lo, hi;
+
+ if (!pgc_clist_byte(pgc, &lo)) return 0;
+ if (!pgc_clist_byte(pgc, &hi)) return 0;
+ *val = (((int16_t)hi) << 8) | lo;
+ return 1;
+ }
+
+ if (!pgc->ascii_mode)
+ {
+ uint8_t lo, hi;
+
+ if (!pgc->inputbyte(pgc, &lo)) return 0;
+ if (!pgc->inputbyte(pgc, &hi)) return 0;
+ *val = (((int16_t)hi) << 8) | lo;
+ return 1;
+ }
+
+ if (!pgc_param_coord(pgc, &c)) return 0;
+
+ c = (c >> 16);
+ if (c > 0x7FFF || c < -0x7FFF)
+ {
+ pgc_error(pgc, PGC_ERROR_RANGE);
+ return 0;
+ }
+ *val = (int16_t)c;
+ return 1;
+}
+
+
+/* Output a byte, either as hex or ASCII depending on the mode */
+int pgc_result_byte(pgc_core_t *pgc, uint8_t val)
+{
+ char buf[20];
+
+ if (!pgc->ascii_mode) return pgc_output_byte(pgc, val);
+
+ if (pgc->result_count)
+ {
+ if (!pgc_output_byte(pgc, ',')) return 0;
+ }
+ sprintf(buf, "%d", val);
+ ++pgc->result_count;
+ return pgc_output_string(pgc, buf);
+}
+
+
+/* Output a word, either as hex or ASCII depending on the mode */
+int pgc_result_word(pgc_core_t *pgc, int16_t val)
+{
+ char buf[20];
+
+ if (!pgc->ascii_mode)
+ {
+ if (!pgc_output_byte(pgc, val & 0xFF)) return 0;
+ return pgc_output_byte(pgc, val >> 8);
+ }
+
+ if (pgc->result_count)
+ {
+ if (!pgc_output_byte(pgc, ',')) return 0;
+ }
+ sprintf(buf, "%d", val);
+ ++pgc->result_count;
+ return pgc_output_string(pgc, buf);
+}
+
+
+/* Write a screen pixel (x and y are raster coordinates, ink is the
+ * value to write) */
+void pgc_write_pixel(pgc_core_t *pgc, uint16_t x, uint16_t y, uint8_t ink)
+{
+ uint8_t *vram;
+
+ /* Suppress out-of-range writes; clip to viewport */
+ if (x < pgc->vp_x1 || x > pgc->vp_x2 || x >= pgc->maxw ||
+ y < pgc->vp_y1 || y > pgc->vp_y2 || y >= pgc->maxh)
+ {
+ PGCLOG(("pgc_write_pixel clipped: (%d,%d) "
+ "vp_x1=%d vp_y1=%d vp_x2=%d vp_y2=%d "
+ "ink=0x%02x\n", x, y,
+ pgc->vp_x1, pgc->vp_y1,
+ pgc->vp_x2, pgc->vp_y2, ink));
+ return;
+ }
+ vram = pgc_vram_addr(pgc, x, y);
+ if (vram) *vram = ink;
+}
+
+/* Read a screen pixel (x and y are raster coordinates) */
+uint8_t pgc_read_pixel(pgc_core_t *pgc, uint16_t x, uint16_t y)
+{
+ uint8_t *vram;
+
+ /* Suppress out-of-range reads */
+ if (x >= pgc->maxw || y >= pgc->maxh)
+ {
+ return 0;
+ }
+ vram = pgc_vram_addr(pgc, x, y);
+ if (vram) return *vram;
+ return 0;
+}
+
+
+
+
+/* Plot a point in the current colour and draw mode. Raster coordinates. */
+void pgc_plot(pgc_core_t *pgc, uint16_t x, uint16_t y)
+{
+ uint8_t *vram;
+
+ /* Only allow plotting within the current viewport. */
+ if (x < pgc->vp_x1 || x > pgc->vp_x2 || x >= pgc->maxw ||
+ y < pgc->vp_y1 || y > pgc->vp_y2 || y >= pgc->maxh)
+ {
+ PGCLOG(("pgc_plot clipped: (%d,%d) %d <= x <= %d; %d <= y <= %d; "
+ "mode=%d ink=0x%02x\n", x, y,
+ pgc->vp_x1, pgc->vp_x2, pgc->vp_y1, pgc->vp_y2,
+ pgc->draw_mode, pgc->colour));
+ return;
+ }
+ vram = pgc_vram_addr(pgc, x, y);
+ if (!vram) return;
+
+ /* TODO: Does not implement the PGC plane mask (set by MASK) */
+ switch (pgc->draw_mode)
+ {
+ default:
+ case 0: *vram = pgc->colour; break; /* Write */
+ case 1: *vram ^= 0xFF; break; /* Invert */
+ case 2: *vram ^= pgc->colour; break; /* XOR colour */
+ case 3: *vram &= pgc->colour; break; /* AND */
+ }
+}
+
+
+/* Given raster coordinates, find the matching address in PGC video RAM */
+uint8_t *pgc_vram_addr(pgc_core_t *pgc, int16_t x, int16_t y)
+{
+ int offset;
+
+/* We work from the bottom left-hand corner */
+ if (y < 0 || y >= pgc->maxh || x < 0 || x >= pgc->maxw) return NULL;
+
+ offset = (pgc->maxh - 1 -y) * (pgc->maxw) + x;
+// PGCLOG(("pgc_vram_addr x=%d y=%d offset=%d\n", x, y, offset);
+
+ if (offset < 0 || offset >= (pgc->maxw * pgc->maxh))
+ {
+ return NULL;
+ }
+ return &pgc->vram[offset];
+}
+
+
+
+/* Read in the next command, either as hex (1 byte) or ASCII (up to 6
+ * characters) */
+int pgc_read_command(pgc_core_t *pgc)
+{
+ if (pgc->clcur)
+ {
+ return pgc_clist_byte(pgc, &pgc->hex_command);
+ }
+ else if (pgc->ascii_mode)
+ {
+ char ch;
+ int count = 0;
+
+ while (count < 7)
+ {
+ if (!pgc_input_char(pgc, &ch)) return 0;
+ if (is_whitespace(ch))
+ {
+ /* Pad to 6 characters */
+ while (count < 6)
+ pgc->asc_command[count++] = ' ';
+ pgc->asc_command[6] = 0;
+ return 1;
+ }
+ pgc->asc_command[count++] = toupper(ch);
+ }
+ return 1;
+ }
+ else
+ {
+ return pgc->inputbyte(pgc, &pgc->hex_command);
+ }
+}
+
+
+/* Read in the next command and parse it */
+static int pgc_parse_command(pgc_core_t *pgc, const pgc_command_t **pcmd)
+{
+ const pgc_command_t *cmd;
+ char match[7];
+
+ *pcmd = NULL;
+ pgc->hex_command = 0;
+ memset(pgc->asc_command, ' ', 6);
+ pgc->asc_command[6] = 0;
+ if (!pgc_read_command(pgc))
+ {
+ /* PGC has been reset */
+ return 0;
+ }
+/* Scan the list of valid commands. pgc->pgc_commands may be a subclass
+ * list (terminated with '*') or the core list (terminated with '@') */
+ for (cmd = pgc->pgc_commands; cmd->ascii[0] != '@'; cmd++)
+ {
+ /* End of subclass command list, chain to core */
+ if (cmd->ascii[0] == '*') cmd = pgc_core_commands;
+
+ /* If in ASCII mode match on the ASCII command */
+ if (pgc->ascii_mode && !pgc->clcur)
+ {
+ sprintf(match, "%-6.6s", cmd->ascii);
+ if (!strncmp(match, pgc->asc_command, 6))
+ {
+ *pcmd = cmd;
+ pgc->hex_command = cmd->hex;
+ break;
+ }
+ }
+ else /* Otherwise match on the hex command */
+ {
+ if (cmd->hex == pgc->hex_command)
+ {
+ sprintf(pgc->asc_command, "%-6.6s",
+ cmd->ascii);
+ *pcmd = cmd;
+ break;
+ }
+ }
+ }
+ return 1;
+}
+
+
+/* The PGC drawing thread main loop. Read in commands and execute them ad
+ * infinitum */
+void pgc_core_thread(void *p)
+{
+ pgc_core_t *pgc = (pgc_core_t *)p;
+ const pgc_command_t *cmd;
+
+ PGCLOG(("pgc_core_thread begins"));
+ while (1)
+ {
+ if (!pgc_parse_command(pgc, &cmd))
+ {
+ /* PGC has been reset */
+ continue;
+ }
+ PGCLOG(("PGC command: [%02x] '%s' found=%d\n",
+ pgc->hex_command, pgc->asc_command, (cmd != NULL)));
+
+ if (cmd)
+ {
+ pgc->result_count = 0;
+ (*cmd->handler)(pgc);
+ }
+ else
+ {
+ pgc_error(pgc, PGC_ERROR_OPCODE);
+ }
+ }
+}
+
+void pgc_recalctimings(pgc_core_t *pgc)
+{
+ double disptime, _dispontime, _dispofftime;
+ double pixel_clock = (cpuclock * (double)(1ull << 32)) / (pgc->cga_selected ? 25175000.0 : pgc->native_pixel_clock);
+
+ /* Use a fixed 640 columns, like the T3100e */
+ disptime = pgc->screenw + 11;
+ _dispontime = pgc->screenw * pixel_clock;
+ _dispofftime = (disptime - pgc->screenw) * pixel_clock;
+ pgc->dispontime = (uint64_t)_dispontime;
+ pgc->dispofftime = (uint64_t)_dispofftime;
+}
+
+/* Draw the display in CGA (640x400) text mode */
+void pgc_cga_text(pgc_core_t *pgc, int w)
+{
+ int x, c;
+ uint8_t chr, attr;
+ int drawcursor = 0;
+ uint32_t cols[2];
+ int pitch = (pgc->mapram[0x3E9] + 1) * 2;
+ uint16_t sc = (pgc->displine & 0x0F) % pitch;
+ uint16_t ma = (pgc->mapram[0x3ED] | (pgc->mapram[0x3EC] << 8)) & 0x3fff;
+ uint16_t ca = (pgc->mapram[0x3EF] | (pgc->mapram[0x3EE] << 8)) & 0x3fff;
+ uint8_t *addr;
+ int cw = (w == 80) ? 8 : 16;
+
+ addr = &pgc->cga_vram[((ma << 1) + (((pgc->displine / pitch)*w)) * 2) & 0x3ffe];
+ ma += (pgc->displine / pitch) * w;
+
+ for (x = 0; x < w; x++)
+ {
+ chr = addr[0];
+ attr = addr[1];
+ addr += 2;
+
+ /* Cursor enabled? */
+ if (ma == ca && (pgc->cgablink & 8) &&
+ (pgc->mapram[0x3EA] & 0x60) != 0x20)
+ {
+ drawcursor = ((pgc->mapram[0x3EA] & 0x1F) <= (sc >> 1))
+ && ((pgc->mapram[0x3EB] & 0x1F) >= (sc >> 1));
+ }
+ else drawcursor = 0;
+ if (pgc->mapram[0x3D8] & 0x20)
+ {
+ cols[1] = attr & 15;
+ cols[0] = (attr >> 4) & 7;
+ if ((pgc->cgablink & 8) && (attr & 0x80) && !drawcursor)
+ cols[1] = cols[0];
+ }
+ else
+ {
+ cols[1] = attr & 15;
+ cols[0] = attr >> 4;
+ }
+ if (drawcursor)
+ {
+ for (c = 0; c < cw; c++)
+ {
+ if (w == 80)
+ ((uint32_t *)buffer32->line[pgc->displine & 2047])[(x << 3) + c] = cols[(fontdatm[chr + pgc->fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff;
+ else
+ ((uint32_t *)buffer32->line[pgc->displine & 2047])[(x << 4) + c] = cols[(fontdatm[chr + pgc->fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff;
+ }
+ }
+ else
+ {
+ for (c = 0; c < cw; c++)
+ {
+ if (w == 80)
+ ((uint32_t *)buffer32->line[pgc->displine & 2047])[(x << 3) + c] = cols[(fontdatm[chr + pgc->fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0];
+ else
+ ((uint32_t *)buffer32->line[pgc->displine & 2047])[(x << 4) + c] = cols[(fontdatm[chr + pgc->fontbase][sc] & (1 << ((c >> 1) ^ 7))) ? 1 : 0];
+ }
+ }
+ ma++;
+ }
+}
+
+
+/* Draw the display in CGA (320x200) graphics mode */
+void pgc_cga_gfx40(pgc_core_t *pgc)
+{
+ int x, c;
+ uint32_t cols[4];
+ int col;
+ uint16_t ma = (pgc->mapram[0x3ED] | (pgc->mapram[0x3EC] << 8)) & 0x3fff;
+ uint8_t *addr;
+ uint16_t dat;
+
+ cols[0] = pgc->mapram[0x3D9] & 15;
+ col = (pgc->mapram[0x3D9] & 16) ? 8 : 0;
+
+ if (pgc->mapram[0x3D8] & 4)
+ {
+ cols[1] = col | 3;
+ cols[2] = col | 4;
+ cols[3] = col | 7;
+ }
+ else if (pgc->mapram[0x3D9] & 32)
+ {
+ cols[1] = col | 3;
+ cols[2] = col | 5;
+ cols[3] = col | 7;
+ }
+ else
+ {
+ cols[1] = col | 2;
+ cols[2] = col | 4;
+ cols[3] = col | 6;
+ }
+ for (x = 0; x < 40; x++)
+ {
+ addr = &pgc->cga_vram[(ma + 2 * x + 80 * (pgc->displine >> 2) + 0x2000 * ((pgc->displine >> 1) & 1)) & 0x3FFF];
+ dat = (addr[0] << 8) | addr[1];
+ pgc->ma++;
+ for (c = 0; c < 8; c++)
+ {
+ ((uint32_t *)buffer32->line[pgc->displine & 2047])[(x << 4) + (c << 1)] =
+ ((uint32_t *)buffer32->line[pgc->displine & 2047])[(x << 4) + (c << 1) + 1] = cols[dat >> 14];
+ dat <<= 2;
+ }
+ }
+}
+
+
+/* Draw the display in CGA (640x200) graphics mode */
+void pgc_cga_gfx80(pgc_core_t *pgc)
+{
+ int x, c;
+ uint32_t cols[2];
+ uint16_t ma = (pgc->mapram[0x3ED] | (pgc->mapram[0x3EC] << 8)) & 0x3fff;
+ uint8_t *addr;
+ uint16_t dat;
+
+ cols[0] = 0;
+ cols[1] = pgc->mapram[0x3D9] & 15;
+
+ for (x = 0; x < 40; x++)
+ {
+ addr = &pgc->cga_vram[(ma + 2 * x + 80 * (pgc->displine >> 2) + 0x2000 * ((pgc->displine >> 1) & 1)) & 0x3FFF];
+ dat = (addr[0] << 8) | addr[1];
+ pgc->ma++;
+ for (c = 0; c < 16; c++)
+ {
+ ((uint32_t *)buffer32->line[pgc->displine & 2047])[(x << 4) + c] = cols[dat >> 15];
+ dat <<= 1;
+ }
+ }
+}
+
+
+
+/* Draw the screen in CGA mode. Based on the simplified WY700 renderer
+ * rather than the original CGA, since the PGC doesn't have a real 6845 */
+void pgc_cga_poll(pgc_core_t *pgc)
+{
+ int c;
+ uint32_t cols[2];
+
+ if (!pgc->linepos)
+ {
+ timer_advance_u64(&pgc->timer, pgc->dispofftime);
+ pgc->mapram[0x3DA] |= 1;
+ pgc->linepos = 1;
+ if (pgc->cgadispon)
+ {
+ if (pgc->displine == 0)
+ {
+ video_wait_for_buffer();
+ }
+
+ if ((pgc->mapram[0x3D8] & 0x12) == 0x12)
+ {
+ pgc_cga_gfx80(pgc);
+ }
+ else if (pgc->mapram[0x3D8] & 0x02)
+ {
+ pgc_cga_gfx40(pgc);
+ }
+ else if (pgc->mapram[0x3D8] & 0x01)
+ {
+ pgc_cga_text(pgc, 80);
+ }
+ else
+ {
+ pgc_cga_text(pgc, 40);
+ }
+ }
+ else
+ {
+ cols[0] = ((pgc->mapram[0x3D8] & 0x12) == 0x12) ? 0 : (pgc->mapram[0x3D9] & 15);
+ hline(buffer32, 0, pgc->displine & 2047, PGC_CGA_WIDTH, cols[0]);
+ }
+
+ for (c = 0; c < PGC_CGA_WIDTH; c++)
+ ((uint32_t *)buffer32->line[pgc->displine & 2047])[c] = cgapal[((uint32_t *)buffer32->line[pgc->displine & 2047])[c] & 0xf];
+
+ pgc->displine++;
+ if (pgc->displine == PGC_CGA_HEIGHT)
+ {
+ pgc->mapram[0x3DA] |= 8;
+ pgc->cgadispon = 0;
+ }
+ if (pgc->displine == PGC_CGA_HEIGHT + 32)
+ {
+ pgc->mapram[0x3DA] &= ~8;
+ pgc->cgadispon = 1;
+ pgc->displine = 0;
+ }
+ }
+ else
+ {
+ if (pgc->cgadispon)
+ {
+ pgc->mapram[0x3DA] &= ~1;
+ }
+ timer_advance_u64(&pgc->timer, pgc->dispontime);
+ pgc->linepos = 0;
+
+ if (pgc->displine == PGC_CGA_HEIGHT)
+ {
+ if (PGC_CGA_WIDTH != xsize || PGC_CGA_HEIGHT != ysize)
+ {
+ xsize = PGC_CGA_WIDTH;
+ ysize = PGC_CGA_HEIGHT;
+ updatewindowsize(xsize, ysize);
+ }
+ video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize);
+ frames++;
+
+ /* We have a fixed 640x400 screen for
+ * CGA modes */
+ video_res_x = PGC_CGA_WIDTH;
+ video_res_y = PGC_CGA_HEIGHT;
+ switch (pgc->mapram[0x3D8] & 0x12)
+ {
+ case 0x12: video_bpp = 1; break;
+ case 0x02: video_bpp = 2; break;
+ default: video_bpp = 0; break;
+ }
+ pgc->cgablink++;
+ }
+ }
+}
+
+
+
+/* Draw the screen in CGA or native mode. */
+void pgc_poll(void *p)
+{
+ pgc_core_t *pgc = (pgc_core_t *)p;
+ int x, y;
+
+ if (pgc->cga_selected)
+ {
+ pgc_cga_poll(pgc);
+ return;
+ }
+/* Not CGA, so must be native mode */
+ if (!pgc->linepos)
+ {
+ timer_advance_u64(&pgc->timer, pgc->dispofftime);
+ pgc->mapram[0x3DA] |= 1;
+ pgc->linepos = 1;
+ if (pgc->cgadispon && pgc->displine < pgc->maxh)
+ {
+ if (pgc->displine == 0)
+ {
+ video_wait_for_buffer();
+ }
+ /* Don't know why pan needs to be multiplied by -2, but
+ * the IM1024 driver uses PAN -112 for an offset of
+ * 224. */
+ y = pgc->displine - 2 * pgc->pan_y;
+ for (x = 0; x < pgc->screenw; x++)
+ {
+ if (x + pgc->pan_x < pgc->maxw)
+ {
+ ((uint32_t *)buffer32->line[pgc->displine & 2047])[x] = pgc->palette[pgc->vram[y * pgc->maxw + x]];
+ }
+ else
+ {
+ ((uint32_t *)buffer32->line[pgc->displine & 2047])[x] = pgc->palette[0];
+ }
+ }
+ }
+ else
+ {
+ hline(buffer32, 0, pgc->displine & 2047, pgc->screenw, pgc->palette[0]);
+ }
+ pgc->displine++;
+ if (pgc->displine == pgc->screenh)
+ {
+ pgc->mapram[0x3DA] |= 8;
+ pgc->cgadispon = 0;
+ }
+ if (pgc->displine == pgc->screenh + 32)
+ {
+ pgc->mapram[0x3DA] &= ~8;
+ pgc->cgadispon = 1;
+ pgc->displine = 0;
+ }
+ }
+ else
+ {
+ if (pgc->cgadispon)
+ {
+ pgc->mapram[0x3DA] &= ~1;
+ }
+ timer_advance_u64(&pgc->timer, pgc->dispontime);
+ pgc->linepos = 0;
+
+ if (pgc->displine == pgc->screenh)
+ {
+ if (pgc->screenw != xsize || pgc->screenh != ysize)
+ {
+ xsize = pgc->screenw;
+ ysize = pgc->screenh;
+ updatewindowsize(xsize, ysize);
+ }
+ video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize);
+ frames++;
+
+ video_res_x = pgc->screenw;
+ video_res_y = pgc->screenh;
+ video_bpp = 8;
+ pgc->cgablink++;
+ }
+ }
+}
+
+
+/* Initialise RAM and registers to default values */
+void pgc_reset(pgc_core_t *pgc)
+{
+ int n;
+
+ memset(pgc->mapram, 0, sizeof(pgc->mapram));
+/* There is no point in emulating the 'CGA disable' jumper as this is only
+ * appropriate for a dual-head system, not emulated by PCEM */
+ pgc->mapram[0x30B] = pgc->cga_enabled = 1;
+ pgc->mapram[0x3F8] = 0x03; /* Minor version */
+ pgc->mapram[0x3F9] = 0x01; /* Minor version */
+ pgc->mapram[0x3FB] = 0xA5; /* } */
+ pgc->mapram[0x3FC] = 0x5A; /* PGC self-test passed */
+ pgc->mapram[0x3FD] = 0x55; /* } */
+ pgc->mapram[0x3FE] = 0x5A; /* } */
+
+ pgc->ascii_mode = 1; /* Start off in ASCII mode */
+ pgc->line_pattern = 0xFFFF;
+ memset(pgc->fill_pattern, 0xFF, sizeof(pgc->fill_pattern));
+ pgc->colour = 0xFF;
+ pgc->tjust_h = 1;
+ pgc->tjust_v = 1;
+
+ /* Reset panning */
+ pgc->pan_x = 0;
+ pgc->pan_y = 0;
+
+ /* Reset clipping */
+ pgc->vp_x1 = 0;
+ pgc->vp_y1 = 0;
+ pgc->vp_x2 = pgc->visw - 1;
+ pgc->vp_y2 = pgc->vish - 1;
+
+ /* Empty command lists */
+ for (n = 0; n < 256; n++)
+ {
+ pgc->clist[n].wrptr = 0;
+ pgc->clist[n].rdptr = 0;
+ pgc->clist[n].repeat = 0;
+ pgc->clist[n].chain = 0;
+ }
+ pgc->clcur = NULL;
+ /* Select CGA display */
+ pgc->cga_selected = -1;
+ pgc_setdisplay(pgc, pgc->cga_enabled);
+ pgc->mapram[0x30C] = pgc->cga_enabled;
+ pgc->mapram[0x30D] = pgc->cga_enabled;
+ /* Default palette is 0 */
+ pgc_init_lut(pgc, 0);
+ hndl_lutsav(pgc);
+}
+
+
+/* Initialisation code common to the PGC and its subclasses.
+ *
+ * Pass the 'input byte' function in since this is overridden in
+ * the IM-1024, and needs to be set before the drawing thread is
+ * launched */
+void pgc_core_init(pgc_core_t *pgc, int maxw, int maxh, int visw, int vish,
+ int (*inpbyte)(struct pgc_core_t *pgc, uint8_t *result), double native_pixel_clock)
+{
+ int n;
+
+ mem_mapping_add(&pgc->mapping, 0xC6000, 0x800,
+ pgc_read, NULL, NULL,
+ pgc_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, pgc);
+ mem_mapping_add(&pgc->cga_mapping, 0xB8000, 0x8000,
+ pgc_read, NULL, NULL,
+ pgc_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, pgc);
+ io_sethandler(0x3D0, 0x0010, pgc_in, NULL, NULL, pgc_out, NULL, NULL,
+ pgc);
+
+ pgc->maxw = maxw;
+ pgc->maxh = maxh;
+ pgc->visw = visw;
+ pgc->vish = vish;
+ pgc->vram = malloc(maxw * maxh);
+ pgc->cga_vram = malloc(0x4000);
+ pgc->clist = calloc(256, sizeof(pgc_commandlist_t));
+ pgc->clcur = NULL;
+ pgc->native_pixel_clock = native_pixel_clock;
+
+ memset(pgc->vram, 0, maxw * maxh);
+ memset(pgc->cga_vram, 0, 0x4000);
+ /* Empty command lists */
+ for (n = 0; n < 256; n++)
+ {
+ pgc->clist[n].list = NULL;
+ pgc->clist[n].listmax = 0;
+ pgc->clist[n].wrptr = 0;
+ pgc->clist[n].rdptr = 0;
+ pgc->clist[n].repeat = 0;
+ pgc->clist[n].chain = NULL;
+ }
+
+ pgc_reset(pgc);
+ pgc->inputbyte = inpbyte;
+ pgc->pgc_commands = pgc_core_commands;
+ pgc->pgc_wake_thread = thread_create_event();
+ pgc->pgc_thread = thread_create(pgc_core_thread, pgc);
+
+ timer_add(&pgc->timer, pgc_poll, (void *)pgc, 1);
+
+ timer_add(&pgc->wake_timer, pgc_wake_timer, (void *)pgc, 0);
+}
+
+
+/* Initialisation code specific to the PGC */
+void *pgc_standalone_init()
+{
+ pgc_core_t *pgc = malloc(sizeof(pgc_core_t));
+ memset(pgc, 0, sizeof(pgc_core_t));
+
+ /* Framebuffer and screen are both 640x480 */
+ pgc_core_init(pgc, 640, 480, 640, 480, pgc_input_byte, 25175000.0);
+ return pgc;
+}
+
+
+void pgc_close(void *p)
+{
+ pgc_core_t *pgc = (pgc_core_t *)p;
+
+ thread_kill(pgc->pgc_thread);
+ thread_destroy_event(pgc->pgc_wake_thread);
+
+ if (pgc->cga_vram)
+ {
+ free(pgc->cga_vram);
+ }
+ if (pgc->vram)
+ {
+ free(pgc->vram);
+ }
+ free(pgc);
+}
+
+void pgc_speed_changed(void *p)
+{
+ pgc_core_t *pgc = (pgc_core_t *)p;
+
+ pgc_recalctimings(pgc);
+}
+
+
+device_config_t pgc_config[] =
+{
+ {
+ .type = -1
+ }
+};
+
+device_t pgc_device =
+{
+ "PGC",
+ 0,
+ pgc_standalone_init,
+ pgc_close,
+ NULL,
+ pgc_speed_changed,
+ NULL,
+ NULL,
+ pgc_config
+};
+
diff --git a/src/vid_pgc.h b/src/vid_pgc.h
new file mode 100644
index 0000000..621f4a3
--- /dev/null
+++ b/src/vid_pgc.h
@@ -0,0 +1,164 @@
+#include "timer.h"
+
+struct pgc_core_t;
+
+typedef struct pgc_commandlist_t
+{
+ uint8_t *list;
+ uint32_t listmax;
+ uint32_t wrptr;
+ uint32_t rdptr;
+ uint32_t repeat;
+ struct pgc_commandlist_t *chain;
+} pgc_commandlist_t;
+
+int pgc_commandlist_append(pgc_commandlist_t *list, uint8_t v);
+
+typedef struct pgc_command_t
+{
+ char ascii[6];
+ uint8_t hex;
+ void (*handler)(struct pgc_core_t *pgc);
+ int (*parser) (struct pgc_core_t *pgc, pgc_commandlist_t *cl,
+ int p);
+ int p;
+} pgc_command_t;
+
+
+typedef struct pgc_core_t
+{
+ mem_mapping_t mapping;
+ mem_mapping_t cga_mapping;
+
+ pgc_commandlist_t *clist;
+ pgc_commandlist_t *clcur;
+ uint8_t mapram[2048]; /* Host <--> PGC communication buffer */
+ uint8_t *cga_vram;
+ uint8_t *vram;
+ char asc_command[7];
+ uint8_t hex_command;
+ uint32_t palette[256];
+ uint32_t userpal[256];
+ uint32_t maxw, maxh; /* Maximum framebuffer size */
+ uint32_t visw, vish; /* Maximum screen size */
+ uint32_t screenw, screenh;
+ int16_t pan_x, pan_y;
+ uint16_t win_x1, win_x2, win_y1, win_y2;
+ uint16_t vp_x1, vp_x2, vp_y1, vp_y2;
+ int16_t fill_pattern[16];
+ int16_t line_pattern;
+ uint8_t draw_mode;
+ uint8_t fill_mode;
+ uint8_t colour;
+ uint8_t tjust_h; /* Horizontal alignment 1=left 2=centre 3=right*/
+ uint8_t tjust_v; /* Vertical alignment 1=bottom 2=centre 3=top*/
+ int32_t tsize; /* Horizontal spacing */
+
+ int32_t x, y, z;/* Drawing position */
+
+ const pgc_command_t *pgc_commands;
+ thread_t *pgc_thread;
+ event_t *pgc_wake_thread;
+ pc_timer_t wake_timer;
+// int wake_timer;
+
+ int waiting_input_fifo;
+ int waiting_output_fifo;
+ int waiting_error_fifo;
+ int cga_enabled;
+ int cga_selected;
+ int ascii_mode;
+ int result_count;
+
+ int fontbase;
+ int linepos, displine;
+ int vc;
+ int cgadispon;
+ int con, coff, cursoron, cgablink;
+ int vsynctime, vadj;
+ uint16_t ma, maback;
+ int oddeven;
+
+ uint64_t dispontime, dispofftime;
+ pc_timer_t timer;
+// int vidtime;
+ double native_pixel_clock;
+
+ int drawcursor;
+
+ int (*inputbyte)(struct pgc_core_t *pgc, uint8_t *result);
+
+} pgc_core_t;
+
+void pgc_init(pgc_core_t *pgc);
+void pgc_out(uint16_t addr, uint8_t val, void *p);
+uint8_t pgc_in(uint16_t addr, void *p);
+void pgc_write(uint32_t addr, uint8_t val, void *p);
+uint8_t pgc_read(uint32_t addr, void *p);
+void pgc_recalctimings(pgc_core_t *pgc);
+void pgc_poll(void *p);
+void pgc_reset(pgc_core_t *pgc);
+void pgc_wake(pgc_core_t *pgc);
+/* Plot a pixel (raster coordinates, current ink) */
+void pgc_plot(pgc_core_t *pgc, uint16_t x, uint16_t y);
+void pgc_write_pixel(pgc_core_t *pgc, uint16_t x, uint16_t y, uint8_t ink);
+uint8_t pgc_read_pixel(pgc_core_t *pgc, uint16_t x, uint16_t y);
+uint8_t *pgc_vram_addr(pgc_core_t *pgc, int16_t x, int16_t y);
+/* Draw line (window coordinates) */
+uint16_t pgc_draw_line(pgc_core_t *pgc, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint16_t linemask);
+/* Draw line (raster coordinates) */
+uint16_t pgc_draw_line_r(pgc_core_t *pgc, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint16_t linemask);
+void pgc_draw_ellipse(pgc_core_t *pgc, int32_t x, int32_t y);
+void pgc_fill_polygon(pgc_core_t *pgc, unsigned corners, int32_t *x, int32_t *y);
+/* Horizontal line in fill pattern (raster coordinates) */
+void pgc_fill_line_r(pgc_core_t *pgc, int32_t x0, int32_t x1, int32_t y);
+
+/* Convert to raster coordinates */
+void pgc_sto_raster(pgc_core_t *pgc, int16_t *x, int16_t *y);
+void pgc_ito_raster(pgc_core_t *pgc, int32_t *x, int32_t *y);
+void pgc_dto_raster(pgc_core_t *pgc, double *x, double *y);
+
+/* Read/write to the PGC's FIFOs */
+int pgc_input_byte(pgc_core_t *pgc, uint8_t *val);
+int pgc_output_byte(pgc_core_t *pgc, uint8_t val);
+int pgc_output_string(pgc_core_t *pgc, const char *val);
+int pgc_error_byte(pgc_core_t *pgc, uint8_t val);
+int pgc_error_string(pgc_core_t *pgc, const char *val);
+
+int pgc_param_byte(pgc_core_t *pgc, uint8_t *val);
+int pgc_param_word(pgc_core_t *pgc, int16_t *val);
+int pgc_param_coord(pgc_core_t *pgc, int32_t *val);
+int pgc_result_byte(pgc_core_t *pgc, uint8_t val);
+int pgc_result_word(pgc_core_t *pgc, int16_t val);
+int pgc_result_coord(pgc_core_t *pgc, int32_t val);
+
+void pgc_sleep(pgc_core_t *pgc);
+int pgc_error(pgc_core_t *pgc, int err);
+void pgc_core_init(pgc_core_t *pgc, int maxw, int maxh, int visw, int vish,
+ int (*inpbyte)(struct pgc_core_t *pgc, uint8_t *result), double native_pixel_clock);
+void pgc_speed_changed(void *p);
+void pgc_close(void *p);
+
+void pgc_hndl_lut8(pgc_core_t *pgc);
+void pgc_hndl_lut8rd(pgc_core_t *pgc);
+
+int pgc_parse_bytes(pgc_core_t *pgc, pgc_commandlist_t *cl, int p);
+int pgc_parse_words(pgc_core_t *pgc, pgc_commandlist_t *cl, int p);
+int pgc_parse_coords(pgc_core_t *pgc, pgc_commandlist_t *cl, int p);
+
+extern device_t pgc_device;
+
+#define PGC_ERROR_RANGE 0x01
+#define PGC_ERROR_INTEGER 0x02
+#define PGC_ERROR_MEMORY 0x03
+#define PGC_ERROR_OVERFLOW 0x04
+#define PGC_ERROR_DIGIT 0x05
+#define PGC_ERROR_OPCODE 0x06
+#define PGC_ERROR_RUNNING 0x07
+#define PGC_ERROR_STACK 0x08
+#define PGC_ERROR_TOOLONG 0x09
+#define PGC_ERROR_AREA 0x0A
+#define PGC_ERROR_MISSING 0x0B
+
+/* #define PGCLOG(x) pclog x */
+#define PGCLOG(x)
diff --git a/src/vid_s3.c b/src/vid_s3.c
index e22e6cd..65adde4 100644
--- a/src/vid_s3.c
+++ b/src/vid_s3.c
@@ -999,13 +999,18 @@ void s3_out(uint16_t addr, uint8_t val, void *p)
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
- if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) return;
+ if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && svga->crtcreg != 0x39 && (svga->crtc[0x38] & 0xcc) != 0x48)
+ {
+ if (!((svga->crtc[0x39] & 0xe0) == 0xa0 && svga->crtcreg >= 0x40 && svga->crtcreg <= 0x6d))
+ return;
+ }
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
switch (svga->crtcreg)
{
case 0x31:
s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4);
+ svga->force_dword_mode = val & 0x08;
break;
case 0x32:
svga->vram_display_mask = (val & 0x40) ? 0x3ffff : s3->vram_mask;
@@ -1186,6 +1191,10 @@ void s3_recalctimings(svga_t *svga)
{
s3_t *s3 = (s3_t *)svga->p;
svga->hdisp = svga->hdisp_old;
+ int clk_sel = (svga->miscout >> 2) & 3;
+
+ if (clk_sel == 3 && s3->chip == S3_VISION864)
+ clk_sel = svga->crtc[0x42] & 0xf;
// pclog("%i %i\n", svga->hdisp, svga->hdisp_time);
// pclog("recalctimings\n");
@@ -1206,7 +1215,7 @@ void s3_recalctimings(svga_t *svga)
else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100;
if (!svga->rowoffset) svga->rowoffset = 256;
svga->interlace = svga->crtc[0x42] & 0x20;
- svga->clock = (cpuclock * (float)(1ull << 32)) / s3->getclock((svga->miscout >> 2) & 3, s3->getclock_p);
+ svga->clock = (cpuclock * (float)(1ull << 32)) / s3->getclock(clk_sel, s3->getclock_p);
switch (svga->crtc[0x67] >> 4)
{
@@ -1654,15 +1663,35 @@ static void polygon_setup(s3_t *s3)
}
}
-#define READ_SRC(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \
- else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \
- else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; \
+/*Remap address for chain-4/doubleword style layout*/
+static inline uint32_t dword_remap(uint32_t in_addr)
+{
+ return ((in_addr << 2) & 0x3fff0) |
+ ((in_addr >> 14) & 0xc) |
+ (in_addr & ~0x3fffc);
+}
+static inline uint32_t dword_remap_w(uint32_t in_addr)
+{
+ return ((in_addr << 2) & 0x1fff8) |
+ ((in_addr >> 14) & 0x6) |
+ (in_addr & ~0x1fffe);
+}
+static inline uint32_t dword_remap_l(uint32_t in_addr)
+{
+ return ((in_addr << 2) & 0xfffc) |
+ ((in_addr >> 14) & 0x3) |
+ (in_addr & ~0xffff);
+}
+
+#define READ_SRC(addr, dat) if (s3->bpp == 0) dat = svga->vram[ dword_remap(addr) & s3->vram_mask]; \
+ else if (s3->bpp == 1) dat = vram_w[dword_remap_w(addr) & (s3->vram_mask >> 1)]; \
+ else dat = vram_l[dword_remap_l(addr) & (s3->vram_mask >> 2)]; \
if (vram_mask) \
dat = ((dat & rd_mask) == rd_mask);
-#define READ_DST(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \
- else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \
- else dat = vram_l[(addr) & (s3->vram_mask >> 2)];
+#define READ_DST(addr, dat) if (s3->bpp == 0) dat = svga->vram[ dword_remap(addr) & s3->vram_mask]; \
+ else if (s3->bpp == 1) dat = vram_w[dword_remap_w(addr) & (s3->vram_mask >> 1)]; \
+ else dat = vram_l[dword_remap_l(addr) & (s3->vram_mask >> 2)];
#define MIX { \
uint32_t old_dest_dat = dest_dat; \
@@ -1691,18 +1720,18 @@ static void polygon_setup(s3_t *s3)
#define WRITE(addr) if (s3->bpp == 0) \
{ \
- svga->vram[(addr) & s3->vram_mask] = dest_dat; \
- svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \
+ svga->vram[dword_remap(addr) & s3->vram_mask] = dest_dat; \
+ svga->changedvram[(dword_remap(addr) & s3->vram_mask) >> 12] = changeframecount; \
} \
else if (s3->bpp == 1) \
{ \
- vram_w[(addr) & (s3->vram_mask >> 1)] = dest_dat; \
- svga->changedvram[((addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \
+ vram_w[dword_remap_w(addr) & (s3->vram_mask >> 1)] = dest_dat; \
+ svga->changedvram[(dword_remap_w(addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \
} \
else \
{ \
- vram_l[(addr) & (s3->vram_mask >> 2)] = dest_dat; \
- svga->changedvram[((addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \
+ vram_l[dword_remap_l(addr) & (s3->vram_mask >> 2)] = dest_dat; \
+ svga->changedvram[(dword_remap_l(addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \
}
void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3)
@@ -1722,10 +1751,30 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3;
uint32_t rd_mask = s3->accel.rd_mask;
int cmd = s3->accel.cmd >> 13;
+ uint32_t srcbase, dstbase;
if ((s3->chip == S3_TRIO64) && (s3->accel.cmd & (1 << 11)))
cmd |= 8;
+ if ((s3->accel.multifunc[13] >> 4) & 7)
+ srcbase = 0x100000 * ((s3->accel.multifunc[13] >> 4) & 3);
+ else
+ srcbase = 0x100000 * ((s3->accel.multifunc[14] >> 2) & 3);
+ if ((s3->accel.multifunc[13] >> 0) & 7)
+ dstbase = 0x100000 * ((s3->accel.multifunc[13] >> 0) & 3);
+ else
+ dstbase = 0x100000 * ((s3->accel.multifunc[14] >> 0) & 3);
+ if (s3->bpp == 1)
+ {
+ srcbase >>= 1;
+ dstbase >>= 1;
+ }
+ else if (s3->bpp == 3)
+ {
+ srcbase >>= 2;
+ dstbase >>= 2;
+ }
+
s3->force_busy = 1;
//return;
// if (!cpu_input) pclog("Start S3 command %i %i, %i %i, %i (clip %i, %i to %i, %i %i)\n", s3->accel.cmd >> 13, s3->accel.cur_x, s3->accel.cur_y, s3->accel.maj_axis_pcnt & 0xfff, s3->accel.multifunc[0] & 0xfff, clip_l, clip_t, clip_r, clip_b, s3->accel.multifunc[0xe] & 0x20);
@@ -1788,8 +1837,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
{
while (count-- && s3->accel.sy >= 0)
{
- if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
- s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
+ if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r &&
+ (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b)
{
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
{
@@ -1838,8 +1887,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
{
while (count-- && s3->accel.sy >= 0)
{
- if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
- s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
+ if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r &&
+ (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b)
{
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
{
@@ -1923,7 +1972,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
s3->accel.cy = s3->accel.cur_y;
if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff;
- s3->accel.dest = s3->accel.cy * s3->width;
+ s3->accel.dest = dstbase + s3->accel.cy * s3->width;
// pclog("Dest %08X (%i, %i) %04X %04X\n", s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.cur_x, s3->accel.cur_x & 0x1000);
}
@@ -1936,8 +1985,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
while (count-- && s3->accel.sy >= 0)
{
- if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
- s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
+ if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r &&
+ (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b)
{
switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
{
@@ -1983,7 +2032,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
if (s3->accel.cmd & 0x80) s3->accel.cy++;
else s3->accel.cy--;
- s3->accel.dest = s3->accel.cy * s3->width;
+ s3->accel.dest = dstbase + s3->accel.cy * s3->width;
s3->accel.sy--;
if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return;
@@ -2013,8 +2062,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
s3->accel.cy = s3->accel.cur_y & 0xfff;
if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff;
- s3->accel.src = s3->accel.cy * s3->width;
- s3->accel.dest = s3->accel.dy * s3->width;
+ s3->accel.src = srcbase + s3->accel.cy * s3->width;
+ s3->accel.dest = dstbase + s3->accel.dy * s3->width;
// pclog("Source %08X Dest %08X (%i, %i) - (%i, %i)\n", s3->accel.src, s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy);
}
@@ -2033,8 +2082,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
{
while (1)
{
- if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
- s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
+ if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r &&
+ (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b)
{
READ_SRC(s3->accel.src + s3->accel.cx, src_dat);
READ_DST(s3->accel.dest + s3->accel.dx, dest_dat);
@@ -2056,8 +2105,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
s3->accel.cy++;
s3->accel.dy++;
- s3->accel.src = s3->accel.cy * s3->width;
- s3->accel.dest = s3->accel.dy * s3->width;
+ s3->accel.src = srcbase + s3->accel.cy * s3->width;
+ s3->accel.dest = dstbase + s3->accel.dy * s3->width;
s3->accel.sy--;
@@ -2070,8 +2119,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
{
while (count-- && s3->accel.sy >= 0)
{
- if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
- s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
+ if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r &&
+ (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b)
{
if (vram_mask)
{
@@ -2144,8 +2193,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
s3->accel.dy--;
}
- s3->accel.src = s3->accel.cy * s3->width;
- s3->accel.dest = s3->accel.dy * s3->width;
+ s3->accel.src = srcbase + s3->accel.cy * s3->width;
+ s3->accel.dest = dstbase + s3->accel.dy * s3->width;
s3->accel.sy--;
@@ -2178,12 +2227,12 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
// s3->accel.cy = (s3->accel.cy & ~7) | (s3->accel.dy & 7);
s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx;
- s3->accel.dest = s3->accel.dy * s3->width;
+ s3->accel.dest = dstbase + s3->accel.dy * s3->width;
s3->accel.cx = s3->accel.dx & 7;
s3->accel.cy = s3->accel.dy & 7;
- s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width);
+ s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width);
// pclog("Source %08X Dest %08X (%i, %i) - (%i, %i)\n", s3->accel.src, s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy);
// dumpregs();
@@ -2198,8 +2247,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
while (count-- && s3->accel.sy >= 0)
{
- if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
- s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
+ if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r &&
+ (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b)
{
if (vram_mask)
{
@@ -2271,8 +2320,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
s3->accel.dy--;
}
- s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width);
- s3->accel.dest = s3->accel.dy * s3->width;
+ s3->accel.src = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width);
+ s3->accel.dest = dstbase + s3->accel.dy * s3->width;
s3->accel.sy--;
@@ -2305,12 +2354,12 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
int y = s3->accel.poly_cy;
int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1;
- s3->accel.dest = y * s3->width;
+ s3->accel.dest = dstbase + y * s3->width;
while (x_count-- && count--)
{
- if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r &&
- s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b)
+ if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r &&
+ (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b)
{
switch (frgd_mix)
{
@@ -2380,15 +2429,15 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
int y = s3->accel.poly_cy;
int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1;
- s3->accel.src = s3->accel.pattern + ((y & 7) * s3->width);
- s3->accel.dest = y * s3->width;
+ s3->accel.src = srcbase + s3->accel.pattern + ((y & 7) * s3->width);
+ s3->accel.dest = dstbase + y * s3->width;
while (x_count-- && count--)
{
int pat_x = s3->accel.poly_x & 7;
- if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r &&
- s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b)
+ if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r &&
+ (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b)
{
if (vram_mask)
{
@@ -2492,8 +2541,10 @@ void s3_hwcursor_draw(svga_t *svga, int displine)
// pclog("HWcursor %i %i\n", svga->hwcursor_latch.x, svga->hwcursor_latch.y);
for (x = 0; x < 64; x += 16)
{
- dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 8) | svga->vram[svga->hwcursor_latch.addr + 1];
- dat[1] = (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3];
+ uint32_t remapped_addr = dword_remap(svga->hwcursor_latch.addr);
+
+ dat[0] = (svga->vram[remapped_addr] << 8) | svga->vram[remapped_addr + 1];
+ dat[1] = (svga->vram[remapped_addr + 2] << 8) | svga->vram[remapped_addr + 3];
for (xx = 0; xx < 16; xx++)
{
if (offset >= svga->hwcursor_latch.x)
@@ -2907,11 +2958,10 @@ static device_config_t s3_bahamas64_config[] =
.description = "2 MB",
.value = 2
},
- {
- .description = "4 MB",
- .value = 4
- },
- /*Vision864 also supports 8 MB, however the Paradise BIOS is buggy (VESA modes don't work correctly)*/
+ /*Vision864 also supports 4 and 8 MB, however the Paradise
+ BIOS is buggy (VESA modes don't work correctly), and UNIVBE and
+ OS/2 Warp misdetect the VRAM size. Bahamas 64 only supports
+ up to 2 MB on the board anyway. */
{
.description = ""
}
diff --git a/src/vid_s3_virge.c b/src/vid_s3_virge.c
index a7059e0..428669b 100644
--- a/src/vid_s3_virge.c
+++ b/src/vid_s3_virge.c
@@ -8,6 +8,7 @@
#include "rom.h"
#include "thread.h"
#include "video.h"
+#include "vid_ddc.h"
#include "vid_s3_virge.h"
#include "vid_svga.h"
#include "vid_svga_render.h"
@@ -235,6 +236,8 @@ typedef struct virge_t
int virge_busy;
uint8_t subsys_stat, subsys_cntl;
+
+ uint8_t serialport;
} virge_t;
static inline void wake_fifo_thread(virge_t *virge)
@@ -306,6 +309,11 @@ enum
#define INT_3DF_EMP (1 << 6)
#define INT_MASK 0xff
+#define SERIAL_PORT_SCW (1 << 0)
+#define SERIAL_PORT_SDW (1 << 1)
+#define SERIAL_PORT_SCR (1 << 2)
+#define SERIAL_PORT_SDR (1 << 3)
+
static void s3_virge_update_irqs(virge_t *virge)
{
if ((virge->svga.crtc[0x32] & 0x10) && (virge->subsys_stat & virge->subsys_cntl & INT_MASK))
@@ -786,6 +794,14 @@ static uint8_t s3_virge_mmio_read(uint32_t addr, void *p)
case 0x83d8: case 0x83d9: case 0x83da: case 0x83db:
case 0x83dc: case 0x83dd: case 0x83de: case 0x83df:
return s3_virge_in(addr & 0x3ff, p);
+
+ case 0xff20: case 0xff21:
+ ret = virge->serialport & ~(SERIAL_PORT_SCR | SERIAL_PORT_SDR);
+ if ((virge->serialport & SERIAL_PORT_SCW) && ddc_read_clock())
+ ret |= SERIAL_PORT_SCR;
+ if ((virge->serialport & SERIAL_PORT_SDW) && ddc_read_data())
+ ret |= SERIAL_PORT_SDR;
+ return ret;
}
return 0xff;
}
@@ -1355,9 +1371,12 @@ static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p)
case 0x83dc: case 0x83dd: case 0x83de: case 0x83df:
s3_virge_out(addr & 0x3ff, val, p);
break;
- }
-
+ case 0xff20:
+ virge->serialport = val;
+ ddc_i2c_change((val & SERIAL_PORT_SCW) ? 1 : 0, (val & SERIAL_PORT_SDW) ? 1 : 0);
+ break;
+ }
}
static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p)
{
@@ -1374,6 +1393,10 @@ static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p)
s3_virge_mmio_write(addr, val, p);
s3_virge_mmio_write(addr + 1, val >> 8, p);
break;
+
+ case 0xff20:
+ s3_virge_mmio_write(addr, val, p);
+ break;
}
}
static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
@@ -1817,6 +1840,10 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
// s3_virge_triangle(virge);
break;
+
+ case 0xff20:
+ s3_virge_mmio_write(addr, val, p);
+ break;
}
}
@@ -2975,7 +3002,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3
y_count -= diff_y;
}
if ((state->y - y_count) < s3d_tri->clip_t)
- y_count = state->y - s3d_tri->clip_t;
+ y_count = (state->y - s3d_tri->clip_t) + 1;
}
for (; y_count > 0; y_count--)
@@ -3018,7 +3045,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3
if (xe < s3d_tri->clip_l)
goto tri_skip_line;
if (xe > s3d_tri->clip_r)
- xe = s3d_tri->clip_r;
+ xe = s3d_tri->clip_r + 1;
if (x < s3d_tri->clip_l)
{
int diff_x = s3d_tri->clip_l - x;
@@ -3043,7 +3070,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3
if (xe > s3d_tri->clip_r)
goto tri_skip_line;
if (xe < s3d_tri->clip_l)
- xe = s3d_tri->clip_l;
+ xe = s3d_tri->clip_l - 1;
if (x > s3d_tri->clip_r)
{
int diff_x = x - s3d_tri->clip_r;
@@ -3068,6 +3095,9 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3
dest_addr = dest_offset + (x * (bpp + 1));
z_addr = z_offset + (x << 1);
+ x &= 0xfff;
+ xe &= 0xfff;
+
for (; x != xe; x = (x + x_dir) & 0xfff)
{
int update = 1;
@@ -3913,6 +3943,11 @@ static void *s3_virge_init()
virge->fifo_not_full_event = thread_create_event();
virge->fifo_thread = thread_create(fifo_thread, virge);
+ ddc_init();
+
+ //TODO ViRGE does not use packed chain4
+ virge->svga.packed_chain4 = 1;
+
return virge;
}
@@ -4009,7 +4044,12 @@ static void *s3_virge_375_init()
virge->wake_fifo_thread = thread_create_event();
virge->fifo_not_full_event = thread_create_event();
virge->fifo_thread = thread_create(fifo_thread, virge);
-
+
+ ddc_init();
+
+ //TODO ViRGE does not use packed chain4
+ virge->svga.packed_chain4 = 1;
+
return virge;
}
diff --git a/src/vid_sdac_ramdac.c b/src/vid_sdac_ramdac.c
index 0c62f23..ba0c3ee 100644
--- a/src/vid_sdac_ramdac.c
+++ b/src/vid_sdac_ramdac.c
@@ -9,14 +9,31 @@ static void sdac_control_write(sdac_ramdac_t *ramdac, svga_t *svga, uint8_t val)
{
ramdac->command = val;
// pclog("RAMDAC command reg now %02X\n", val);
- switch (val >> 4)
+ switch (val & 0xf0)
{
- case 0x2: case 0x3: case 0xa: svga->bpp = 15; break;
- case 0x4: case 0xe: svga->bpp = 24; break;
- case 0x5: case 0x6: case 0xc: svga->bpp = 16; break;
- case 0x7: svga->bpp = 32; break;
-
- case 0: case 1: default: svga->bpp = 8; break;
+ case 0x00: case 0x10:
+ svga->bpp = 8;
+ break;
+
+ case 0x20: case 0x30: case 0x80: case 0xa0:
+ svga->bpp = 15;
+ break;
+
+ case 0x50: case 0x60: case 0xc0:
+ svga->bpp = 16;
+ break;
+
+ case 0x40: case 0x90: case 0xe0:
+ svga->bpp = 24;
+ break;
+
+ case 0x70:
+ svga->bpp = 32;
+ break;
+
+ default:
+ svga->bpp = 8;
+ break;
}
}
@@ -96,7 +113,6 @@ void sdac_ramdac_out(uint16_t addr, uint8_t val, sdac_ramdac_t *ramdac, svga_t *
uint8_t sdac_ramdac_in(uint16_t addr, sdac_ramdac_t *ramdac, svga_t *svga)
{
- uint8_t temp;
// /*if (CS!=0xC000) */pclog("IN RAMDAC %04X %04X:%04X %i %i %i\n",addr,CS,cpu_state.pc, ramdac->rs2, ramdac->rindex, ramdac->windex);
switch (addr)
{
@@ -105,15 +121,15 @@ uint8_t sdac_ramdac_in(uint16_t addr, sdac_ramdac_t *ramdac, svga_t *svga)
ramdac->magic_count++;
if (ramdac->magic_count == 4)
{
- temp = 0x70; /*SDAC ID*/
ramdac->rs2 = 1;
+ return 0x70; /*SDAC ID*/
}
if (ramdac->magic_count == 5)
{
- temp = ramdac->command;
ramdac->magic_count = 0;
+ return ramdac->command;
}
- return temp;
+ break;
case 3:
ramdac->magic_count=0;
break;
@@ -148,10 +164,14 @@ float sdac_getclock(int clock, void *p)
sdac_ramdac_t *ramdac = (sdac_ramdac_t *)p;
float t;
int m, n1, n2;
+
+ if (ramdac->regs[0xe] & (1 << 5))
+ clock = ramdac->regs[0xe] & 7;
+
// pclog("SDAC_Getclock %i %04X\n", clock, ramdac->regs[clock]);
+ clock &= 7;
if (clock == 0) return 25175000.0;
if (clock == 1) return 28322000.0;
- clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/
m = (ramdac->regs[clock] & 0x7f) + 2;
n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2;
n2 = ((ramdac->regs[clock] >> 13) & 0x07);
diff --git a/src/vid_sigma.c b/src/vid_sigma.c
new file mode 100644
index 0000000..99235c2
--- /dev/null
+++ b/src/vid_sigma.c
@@ -0,0 +1,979 @@
+#include
+#include
+#include "ibm.h"
+#include "device.h"
+#include "io.h"
+#include "mem.h"
+#include "rom.h"
+#include "timer.h"
+#include "video.h"
+#include "vid_sigma.h"
+
+
+/* The Sigma Designs Color 400 is a video card from 1985, presumably intended
+ * as an EGA competitor.
+ *
+ * The hardware seems to have gone through various iterations; I've seen
+ * pictures of full-length and half-length versions.
+ * TH99 describes the jumpers / switches:
+ *
+ *
+ * The card is CGA-compatible at BIOS level, but to improve compatibility
+ * attempts to write to the CGA I/O ports at 0x3D0-0x3DF trigger an NMI. The
+ * card's BIOS handles the NMI and translates the CGA writes into commands
+ * to its own hardware at 0x2D0-0x2DF. (DIP switches on the card allow the
+ * base address to be changed, but since the BIOS dump I have doesn't support
+ * this I haven't emulated it. Likewise the BIOS ROM address can be changed,
+ * but I'm going with the default of 0xC0000).
+ *
+ * The BIOS still functions if the NMI system isn't operational. There
+ * doesn't seem to be a jumper or DIP switch to lock it out, but at startup
+ * the BIOS tests for its presence and configures itself to work or not
+ * as required. I've therefore added a configuration option to handle this.
+ *
+ * The card's real CRTC at 0x2D0/0x2D1 appears to be a 6845. One oddity is
+ * that all its horizontal counts are halved compared to what a real CGA
+ * uses; 40-column modes have a width of 20, and 80-column modes have a
+ * width of 40. This means that the CRTC cursor position (registers 14/15) can
+ * only address even-numbered columns, so the top bit of the control
+ * register at 0x2D9 is used to adjust the position.
+ *
+ * Apart from the CRTC, registers are:
+ *
+ * 0x2D8: Mode register. Values written by the card BIOS are:
+ * Text 40x25: 0xA8
+ * Text 80x25: 0xB9
+ * Text 80x30: 0xB9
+ * Text 80x50: 0x79
+ * Graphics 320x200: 0x0F
+ * Graphics 640x200: 0x1F
+ * Graphics 640x400: 0x7F
+ *
+ * I have assumed this is a bitmap with the following meaning: */
+#define MODE_80COLS 0x01 /* For text modes, 80 columns across */
+#define MODE_GRAPHICS 0x02 /* Graphics mode */
+#define MODE_NOBLINK 0x04 /* Disable blink? */
+#define MODE_ENABLE 0x08 /* Enable display */
+#define MODE_HRGFX 0x10 /* For graphics modes, 640 pixels across */
+#define MODE_640x400 0x40 /* 400-line graphics mode */
+#define MODE_FONT16 0x80 /* Use 16-pixel high font */
+/*
+ * 0x2D9: Control register, with the following bits: */
+#define CTL_CURSOR 0x80 /* Low bit of cursor position */
+#define CTL_NMI 0x20 /* Writes to 0x3D0-0x3DF trigger NMI */
+#define CTL_CLEAR_LPEN 0x08 /* Strobe 0 to clear lightpen latch */
+#define CTL_SET_LPEN 0x04 /* Strobe 0 to set lightpen latch */
+#define CTL_PALETTE 0x01 /* 0x2DE writes to palette (1) or plane (0) */
+/*
+ * The card BIOS seems to support two variants of the hardware: One where
+ * bits 2 and 3 are normally 1 and are set to 0 to set/clear the latch, and
+ * one where they are normally 0 and are set to 1. Behaviour is selected by
+ * whether the byte at C000:17FFh is greater than 2Fh.
+ *
+ * 0x2DA: Status register.
+ */
+#define STATUS_CURSOR 0x80 /* Last value written to bit 7 of 0x2D9 */
+#define STATUS_NMI 0x20 /* Last value written to bit 5 of 0x2D9 */
+#define STATUS_RETR_V 0x10 /* Vertical retrace */
+#define STATUS_LPEN_T 0x04 /* Lightpen switch is off */
+#define STATUS_LPEN_A 0x02 /* Edge from lightpen has set trigger */
+#define STATUS_RETR_H 0x01 /* Horizontal retrace */
+/*
+ * 0x2DB: On read: Byte written to the card that triggered NMI
+ * 0x2DB: On write: Resets the 'card raised NMI' flag.
+ * 0x2DC: On read: Bit 7 set if the card raised NMI. If so, bits 0-3
+ * give the low 4 bits of the I/O port address.
+ * 0x2DC: On write: Resets the NMI.
+ * 0x2DD: Memory paging. The memory from 0xC1800 to 0xC1FFF can be either:
+ *
+ * > ROM: A 128 character 8x16 font for use in graphics modes
+ * > RAM: Use by the video BIOS to hold its settings.
+ *
+ * Reading port 2DD switches to ROM. Bit 7 of the value read gives the
+ * previous paging state: bit 7 set if ROM was paged, clear if RAM was
+ * paged.
+ *
+ * Writing port 2DD switches to RAM.
+ *
+ * 0x2DE: Meaning depends on bottom bit of value written to port 0x2D9.
+ * Bit 0 set: Write to palette. High 4 bits of value = register,
+ * low 4 bits = RGBI values (active low)
+ * Bit 0 clear: Write to plane select. Low 2 bits of value select
+ * plane 0-3
+ */
+
+
+typedef struct sigma_t
+{
+ mem_mapping_t mapping;
+ mem_mapping_t bios_ram;
+ rom_t bios_rom;
+
+ uint8_t lastport; /* Last I/O port written */
+ uint8_t lastwrite; /* Value written to that port */
+ uint8_t sigma_ctl; /* Controls register:
+ * Bit 7 is low bit of cursor position
+ * Bit 5 set if writes to CGA ports trigger NMI
+ * Bit 3 clears lightpen latch
+ * Bit 2 sets lightpen latch
+ * Bit 1 controls meaning of port 2DE
+ */
+ uint8_t enable_nmi; /* Enable the NMI mechanism for CGA emulation?*/
+ uint8_t rom_paged; /* Is ROM paged in at 0xC1800? */
+
+ uint8_t crtc_value; /* Value to return from a CRTC register read */
+
+ int crtcreg; /* CRTC: Real selected register */
+ uint8_t crtc[32]; /* CRTC: Real values */
+
+ uint8_t sigmastat; /* Status register [0x2DA] */
+
+ uint8_t sigmamode; /* Mode control register [0x2D8] */
+
+ int linepos, displine;
+ int sc, vc;
+ int cgadispon;
+ int con, coff, cursoron, cgablink;
+ int vsynctime, vadj;
+ uint16_t ma, maback;
+ int oddeven;
+
+ uint64_t dispontime, dispofftime;
+ pc_timer_t timer;
+
+ int firstline, lastline;
+
+ int drawcursor;
+
+ uint8_t *vram;
+ uint8_t bram[2048];
+
+ uint8_t palette[16];
+
+ int plane;
+ int revision;
+} sigma_t;
+
+#define COMPOSITE_OLD 0
+#define COMPOSITE_NEW 1
+
+static uint8_t crtcmask[32] =
+{
+ 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+void sigma_recalctimings(sigma_t *cga);
+
+void sigma_out(uint16_t addr, uint8_t val, void *p)
+{
+ sigma_t *sigma = (sigma_t *)p;
+ uint8_t old;
+
+// pclog("SIGMA_OUT %04X %02X\n", addr, val);
+
+// if (addr == 0x3D8 && (val & 0x80)) output = 3;
+
+ if (addr >= 0x3D0 && addr < 0x3E0)
+ {
+ sigma->lastport = addr & 0x0F;
+ sigma->lastwrite = val;
+ /* If set to NMI on video I/O... */
+ if (sigma->enable_nmi && (sigma->sigma_ctl & CTL_NMI))
+ {
+ sigma->lastport |= 0x80; /* Card raised NMI */
+ nmi = 1;
+// pclog("Sigma: Raise NMI\n");
+ }
+ /* For CRTC emulation, the card BIOS sets the value to be
+ * read from port 0x3D1 like this */
+ if (addr == 0x3D1)
+ sigma->crtc_value = val;
+ }
+ else switch (addr)
+ {
+ case 0x2D0:
+ case 0x2D2:
+ case 0x2D4:
+ case 0x2D6:
+ sigma->crtcreg = val & 31;
+ return;
+
+ case 0x2D1:
+ case 0x2D3:
+ case 0x2D5:
+ case 0x2D7:
+ old = sigma->crtc[sigma->crtcreg];
+ sigma->crtc[sigma->crtcreg] = val & crtcmask[sigma->crtcreg];
+// pclog("Sigma: CRTC[0x%02x] := 0x%02x\n",
+// sigma->crtcreg, val);
+ if (old != val)
+ {
+ if (sigma->crtcreg < 0xe || sigma->crtcreg > 0x10)
+ {
+ fullchange = changeframecount;
+ sigma_recalctimings(sigma);
+ }
+ }
+ return;
+
+ case 0x2D8:
+// pclog("Sigma mode := %02x\n", val);
+ sigma->sigmamode = val;
+ return;
+ case 0x2D9:
+// pclog("Sigma control := %02x\n", val);
+ sigma->sigma_ctl = val;
+ return;
+ case 0x2DB:
+ sigma->lastport &= 0x7F;
+ return;
+ case 0x2DC: /* Reset NMI */
+ nmi = 0;
+ sigma->lastport &= 0x7F;
+// pclog("Sigma: Reset NMI\n");
+ return;
+ case 0x2DD: /* Page in RAM at 0xC1800 */
+ if (sigma->rom_paged != 0)
+ mmu_invalidate(0xC0000);
+ sigma->rom_paged = 0;
+// pclog("Sigma: page RAM at C1800\n");
+ return;
+
+ case 0x2DE:
+ if (sigma->sigma_ctl & CTL_PALETTE)
+ {
+// pclog("Sigma: Write palette %x := %x\n",
+// val >> 4, val & 0x0F);
+ sigma->palette[val >> 4] = (val & 0x0F) ^ 0x0F;
+ }
+ else
+ {
+// pclog("Sigma: Set plane to %d\n", val & 3);
+ sigma->plane = val & 3;
+ }
+ return;
+ }
+}
+
+uint8_t sigma_in(uint16_t addr, void *p)
+{
+ uint8_t result = 0xFF;
+ sigma_t *sigma = (sigma_t *)p;
+
+ switch (addr)
+ {
+ case 0x2D0:
+ case 0x2D2:
+ case 0x2D4:
+ case 0x2D6:
+ result = sigma->crtcreg;
+ break;
+
+ case 0x2D1:
+ case 0x2D3:
+ case 0x2D5:
+ case 0x2D7:
+ result = sigma->crtc[sigma->crtcreg & 0x1F];
+ break;
+
+ case 0x2DA:
+ result = (sigma->sigma_ctl & 0xE0) |
+ (sigma->sigmastat & 0x1F);
+ break;
+
+ case 0x2DB:
+ result = sigma->lastwrite; /* Value that triggered NMI */
+ break;
+ case 0x2DC:
+ result = sigma->lastport; /* Port that triggered NMI */
+ break;
+ case 0x2DD: /* Page in ROM at 0xC1800 */
+// pclog("Sigma: page ROM at C1800\n");
+ result = (sigma->rom_paged ? 0x80 : 0);
+ if (sigma->rom_paged != 0x80)
+ mmu_invalidate(0xC0000);
+ sigma->rom_paged = 0x80;
+ break;
+
+ case 0x3D1:
+ case 0x3D3:
+ case 0x3D5:
+ case 0x3D7:
+ result = sigma->crtc_value;
+ break;
+
+/* For CGA compatibility we have to return something palatable on this port.
+ * On a real card this functionality can be turned on or off with SW1/6 */
+ case 0x3DA:
+ result = sigma->sigmastat & 7;
+ if (sigma->sigmastat & STATUS_RETR_V) result |= 8;
+ break;
+ }
+// pclog("SIGMA_IN %04X = %02x\n", addr, result);
+ return result;
+}
+
+void sigma_write(uint32_t addr, uint8_t val, void *p)
+{
+ sigma_t *sigma = (sigma_t *)p;
+
+// pclog("CGA_WRITE %04X %02X\n", addr, val);
+ sigma->vram[sigma->plane * 0x8000 + (addr & 0x7fff)] = val;
+ egawrites++;
+ cycles -= 4;
+}
+
+uint8_t sigma_read(uint32_t addr, void *p)
+{
+ sigma_t *sigma = (sigma_t *)p;
+
+ cycles -= 4;
+ egareads++;
+// pclog("CGA_READ %04X\n", addr);
+ return sigma->vram[sigma->plane * 0x8000 + (addr & 0x7fff)];
+}
+
+void sigma_bwrite(uint32_t addr, uint8_t val, void *p)
+{
+ sigma_t *sigma = (sigma_t *)p;
+
+ addr &= 0x3FFF;
+ if (addr < 0x1800 || sigma->rom_paged || addr >= 0x2000)
+ {
+// pclog("sigma_bwrite(0x%05x) := [ROM] %02x\n", addr, val);
+ }
+ else
+ {
+// pclog("sigma_bwrite(0x%05x) := [RAM] %02x\n", addr, val);
+ sigma->bram[addr & 0x7FF] = val;
+ }
+}
+
+uint8_t sigma_bread(uint32_t addr, void *p)
+{
+ sigma_t *sigma = (sigma_t *)p;
+ uint8_t result;
+
+ addr &= 0x3FFF;
+ if (addr >= 0x2000)
+ {
+// if (output == 3) pclog("sigma_bread(0x%05x) = [NIL] %02x\n",
+// addr, 0xFF);
+ return 0xFF;
+ }
+ if (addr < 0x1800 || sigma->rom_paged)
+ {
+ result = sigma->bios_rom.rom[addr & 0x1FFF];
+// if (output == 3) pclog("sigma_bread(0x%05x) = [ROM] %02x\n", addr, result);
+ }
+ else
+ {
+ result = sigma->bram[addr & 0x7FF];
+// if (output == 3) pclog("sigma_bread(0x%05x) = [RAM] %02x\n", addr, result);
+ }
+ return result;
+}
+
+
+
+void sigma_recalctimings(sigma_t *sigma)
+{
+ double disptime;
+ double _dispontime, _dispofftime;
+// pclog("Sigma_recalctimings - total=%i displayed=%i hi-res=%i\n",
+// sigma->crtc[0], sigma->crtc[1], sigma->sigmamode & MODE_80COLS);
+ if (sigma->sigmamode & MODE_80COLS)
+ {
+ disptime = (sigma->crtc[0] + 1) << 1;
+ _dispontime = (sigma->crtc[1]) << 1;
+ }
+ else
+ {
+ disptime = (sigma->crtc[0] + 1) << 2;
+ _dispontime = sigma->crtc[1] << 2;
+ }
+ _dispofftime = disptime - _dispontime;
+// printf("%i %f %f %f %i %i\n",cgamode&1,disptime,dispontime,dispofftime,crtc[0],crtc[1]);
+ _dispontime *= CGACONST;
+ _dispofftime *= CGACONST;
+// printf("Timings - on %f off %f frame %f second %f\n",dispontime,dispofftime,(dispontime+dispofftime)*262.0,(dispontime+dispofftime)*262.0*59.92);
+ sigma->dispontime = (uint64_t)_dispontime;
+ sigma->dispofftime = (uint64_t)_dispofftime;
+}
+
+
+
+
+/* Render a line in 80-column text mode */
+void sigma_text80(sigma_t *sigma)
+{
+ int x, c;
+ uint8_t chr, attr;
+ uint16_t ca = (sigma->crtc[15] | (sigma->crtc[14] << 8));
+ uint16_t ma = ((sigma->ma & 0x3FFF) << 1);
+ int drawcursor;
+ uint32_t cols[4];
+ uint8_t *vram = sigma->vram + (ma << 1);
+
+ ca = ca << 1;
+ if (sigma->sigma_ctl & CTL_CURSOR) ++ca;
+ ca &= 0x3fff;
+// pclog("sigma_text80: displine=%d sc=%d Width=%d\n",
+// sigma->displine, sigma->sc, sigma->crtc[1]);
+
+ /* The Sigma 400 seems to use screen widths stated in words
+ * (40 for 80-column, 20 for 40-column) */
+ for (x = 0; x < (sigma->crtc[1] << 1); x++)
+ {
+ chr = vram[x << 1];
+ attr = vram[(x << 1) + 1];
+ drawcursor = ((ma == ca) && sigma->con && sigma->cursoron);
+
+ if (!(sigma->sigmamode & MODE_NOBLINK))
+ {
+ cols[1] = attr & 15;
+ cols[0] = (attr >> 4) & 7;
+ if ((sigma->cgablink & 8) && (attr & 0x80) && !sigma->drawcursor)
+ cols[1] = cols[0];
+ }
+ else /* No blink */
+ {
+ cols[1] = attr & 15;
+ cols[0] = attr >> 4;
+ }
+// if (chr != ' ')
+// {
+// pclog("[%x:%x]%c", cols[1], cols[0], chr);
+// }
+ if (drawcursor)
+ {
+ for (c = 0; c < 8; c++)
+ {
+ if (sigma->sigmamode & MODE_FONT16)
+ ((uint32_t *)buffer32->line[sigma->displine])[(x << 3) + c + 8] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff;
+ else ((uint32_t *)buffer32->line[sigma->displine])[(x << 3) + c + 8] = cols[(fontdat[chr][sigma->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff;
+ }
+ }
+ else
+ {
+ for (c = 0; c < 8; c++)
+ {
+ if (sigma->sigmamode & MODE_FONT16)
+ ((uint32_t *)buffer32->line[sigma->displine])[(x << 3) + c + 8] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0];
+ else ((uint32_t *)buffer32->line[sigma->displine])[(x << 3) + c + 8] = cols[(fontdat[chr][sigma->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
+ }
+ }
+ ++ma;
+ }
+ sigma->ma += sigma->crtc[1];
+ //pclog("\n");
+}
+
+
+/* Render a line in 40-column text mode */
+void sigma_text40(sigma_t *sigma)
+{
+ int x, c;
+ uint8_t chr, attr;
+ uint16_t ca = (sigma->crtc[15] | (sigma->crtc[14] << 8));
+ uint16_t ma = ((sigma->ma & 0x3FFF) << 1);
+ int drawcursor;
+ uint32_t cols[4];
+ uint8_t *vram = sigma->vram + ((ma << 1) & 0x3FFF);
+
+ ca = ca << 1;
+ if (sigma->sigma_ctl & CTL_CURSOR) ++ca;
+ ca &= 0x3fff;
+ /* The Sigma 400 seems to use screen widths stated in words
+ * (40 for 80-column, 20 for 40-column) */
+ for (x = 0; x < (sigma->crtc[1] << 1); x++)
+ {
+ chr = vram[x << 1];
+ attr = vram[(x << 1) + 1];
+ drawcursor = ((ma == ca) && sigma->con && sigma->cursoron);
+
+ if (!(sigma->sigmamode & MODE_NOBLINK))
+ {
+ cols[1] = attr & 15;
+ cols[0] = (attr >> 4) & 7;
+ if ((sigma->cgablink & 8) && (attr & 0x80) && !sigma->drawcursor)
+ cols[1] = cols[0];
+ }
+ else /* No blink */
+ {
+ cols[1] = attr & 15;
+ cols[0] = attr >> 4;
+ }
+// if (chr != ' ')
+// {
+// pclog("[%x:%x]%c", cols[1], cols[0], chr);
+// }
+ if (drawcursor)
+ {
+ for (c = 0; c < 8; c++)
+ {
+ ((uint32_t *)buffer32->line[sigma->displine])[(x << 4) + 2*c + 8] =
+ ((uint32_t *)buffer32->line[sigma->displine])[(x << 4) + 2*c + 9] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff;
+ }
+ }
+ else
+ {
+ for (c = 0; c < 8; c++)
+ {
+ ((uint32_t *)buffer32->line[sigma->displine])[(x << 4) + 2*c + 8] =
+ ((uint32_t *)buffer32->line[sigma->displine])[(x << 4) + 2*c + 9] = cols[(fontdatm[chr][sigma->sc & 15] & (1 << (c ^ 7))) ? 1 : 0];
+ }
+ }
+ ma++;
+ }
+ sigma->ma += sigma->crtc[1];
+ //pclog("\n");
+}
+
+
+
+
+/* Draw a line in the 640x400 graphics mode */
+void sigma_gfx400(sigma_t *sigma)
+{
+ int x;
+ unsigned char *vram = &sigma->vram[((sigma->ma << 1) & 0x1FFF)
+ + (sigma->sc & 3) * 0x2000];
+ uint8_t plane[4];
+ uint8_t mask, col, c;
+
+ for (x = 0; x < (sigma->crtc[1] << 1); x++)
+ {
+ plane[0] = vram[x];
+ plane[1] = vram[0x8000 + x];
+ plane[2] = vram[0x10000 + x];
+ plane[3] = vram[0x18000 + x];
+
+ for (c = 0, mask = 0x80; c < 8; c++, mask >>= 1)
+ {
+ col = ((plane[3] & mask) ? 8 : 0) |
+ ((plane[2] & mask) ? 4 : 0) |
+ ((plane[1] & mask) ? 2 : 0) |
+ ((plane[0] & mask) ? 1 : 0);
+ ((uint32_t *)buffer32->line[sigma->displine])[(x << 3) + c + 8] = col;
+ }
+ if (x & 1) ++sigma->ma;
+ }
+}
+
+
+/* Draw a line in the 640x200 graphics mode.
+ * This is actually a 640x200x16 mode; on startup, the BIOS selects plane 2,
+ * blanks the other planes, and sets palette ink 4 to white. Pixels plotted
+ * in plane 2 come out in white, others black; but by programming the palette
+ * and plane registers manually you can get the full resolution. */
+void sigma_gfx200(sigma_t *sigma)
+{
+ int x;
+ unsigned char *vram = &sigma->vram[((sigma->ma << 1) & 0x1FFF)
+ + (sigma->sc & 2) * 0x1000];
+ uint8_t plane[4];
+ uint8_t mask, col, c;
+
+ for (x = 0; x < (sigma->crtc[1] << 1); x++)
+ {
+ plane[0] = vram[x];
+ plane[1] = vram[0x8000 + x];
+ plane[2] = vram[0x10000 + x];
+ plane[3] = vram[0x18000 + x];
+
+ for (c = 0, mask = 0x80; c < 8; c++, mask >>= 1)
+ {
+ col = ((plane[3] & mask) ? 8 : 0) |
+ ((plane[2] & mask) ? 4 : 0) |
+ ((plane[1] & mask) ? 2 : 0) |
+ ((plane[0] & mask) ? 1 : 0);
+ ((uint32_t *)buffer32->line[sigma->displine])[(x << 3) + c + 8] = col;
+ }
+ if (x & 1) ++sigma->ma;
+ }
+}
+
+
+
+
+
+/* Draw a line in the 320x200 graphics mode */
+void sigma_gfx4col(sigma_t *sigma)
+{
+ int x;
+ unsigned char *vram = &sigma->vram[((sigma->ma << 1) & 0x1FFF)
+ + (sigma->sc & 2) * 0x1000];
+ uint8_t plane[4];
+ uint8_t mask, col, c;
+
+ for (x = 0; x < (sigma->crtc[1] << 1); x++)
+ {
+ plane[0] = vram[x];
+ plane[1] = vram[0x8000 + x];
+ plane[2] = vram[0x10000 + x];
+ plane[3] = vram[0x18000 + x];
+
+ mask = 0x80;
+ for (c = 0; c < 4; c++)
+ {
+ col = ((plane[3] & mask) ? 2 : 0) |
+ ((plane[2] & mask) ? 1 : 0);
+ mask = mask >> 1;
+ col |= ((plane[3] & mask) ? 8 : 0) |
+ ((plane[2] & mask) ? 4 : 0);
+ mask = mask >> 1;
+
+ ((uint32_t *)buffer32->line[sigma->displine])[(x << 3) + (c << 1) + 8] =
+ ((uint32_t *)buffer32->line[sigma->displine])[(x << 3) + (c << 1) + 9] = col;
+ }
+ if (x & 1) ++sigma->ma;
+ }
+}
+
+
+
+
+void sigma_poll(void *p)
+{
+ sigma_t *sigma = (sigma_t *)p;
+ int x, c;
+ int oldvc;
+ uint32_t cols[4];
+ int oldsc;
+
+ if (!sigma->linepos)
+ {
+ timer_advance_u64(&sigma->timer, sigma->dispofftime);
+ sigma->sigmastat |= STATUS_RETR_H;
+ sigma->linepos = 1;
+ oldsc = sigma->sc;
+ if ((sigma->crtc[8] & 3) == 3)
+ sigma->sc = ((sigma->sc << 1) + sigma->oddeven) & 7;
+ if (sigma->cgadispon)
+ {
+ if (sigma->displine < sigma->firstline)
+ {
+ sigma->firstline = sigma->displine;
+ video_wait_for_buffer();
+// printf("Firstline %i\n",firstline);
+ }
+ sigma->lastline = sigma->displine;
+
+ cols[0] = 0;
+ // Left overscan
+ for (c = 0; c < 8; c++)
+ {
+ ((uint32_t *)buffer32->line[sigma->displine])[c] = cols[0];
+ if (sigma->sigmamode & MODE_80COLS)
+ ((uint32_t *)buffer32->line[sigma->displine])[c + (sigma->crtc[1] << 4) + 8] = cols[0];
+ else
+ ((uint32_t *)buffer32->line[sigma->displine])[c + (sigma->crtc[1] << 5) + 8] = cols[0];
+ }
+ if (sigma->sigmamode & MODE_GRAPHICS)
+ {
+ if (sigma->sigmamode & MODE_640x400)
+ {
+ sigma_gfx400(sigma);
+ }
+ else if (sigma->sigmamode & MODE_HRGFX)
+ {
+ sigma_gfx200(sigma);
+ }
+ else sigma_gfx4col(sigma);
+
+ }
+ else /* Text modes */
+ {
+ if (sigma->sigmamode & MODE_80COLS)
+ {
+ sigma_text80(sigma);
+ }
+ else
+ {
+ sigma_text40(sigma);
+ }
+ }
+ }
+ else
+ {
+ cols[0] = 0;
+ if (sigma->sigmamode & MODE_80COLS)
+ hline(buffer32, 0, sigma->displine, (sigma->crtc[1] << 4) + 16, cols[0]);
+ else hline(buffer32, 0, sigma->displine, (sigma->crtc[1] << 5) + 16, cols[0]);
+ }
+
+ if (sigma->sigmamode & MODE_80COLS)
+ {
+ x = (sigma->crtc[1] << 4) + 16;
+ }
+ else
+ {
+ x = (sigma->crtc[1] << 5) + 16;
+ }
+
+ for (c = 0; c < x; c++)
+ {
+ ((uint32_t *)buffer32->line[sigma->displine])[c] = cgapal[sigma->palette[((uint32_t *)buffer32->line[sigma->displine])[c] & 0xf]];
+ }
+
+ sigma->sc = oldsc;
+ if (sigma->vc == sigma->crtc[7] && !sigma->sc)
+ sigma->sigmastat |= STATUS_RETR_V;
+ sigma->displine++;
+ if (sigma->displine >= 560)
+ sigma->displine = 0;
+ }
+ else
+ {
+ timer_advance_u64(&sigma->timer, sigma->dispontime);
+ sigma->linepos = 0;
+ if (sigma->vsynctime)
+ {
+ sigma->vsynctime--;
+ if (!sigma->vsynctime)
+ sigma->sigmastat &= ~STATUS_RETR_V;
+ }
+ if (sigma->sc == (sigma->crtc[11] & 31) || ((sigma->crtc[8] & 3) == 3 && sigma->sc == ((sigma->crtc[11] & 31) >> 1)))
+ {
+ sigma->con = 0;
+ sigma->coff = 1;
+ }
+ if ((sigma->crtc[8] & 3) == 3 && sigma->sc == (sigma->crtc[9] >> 1))
+ sigma->maback = sigma->ma;
+ if (sigma->vadj)
+ {
+ sigma->sc++;
+ sigma->sc &= 31;
+ sigma->ma = sigma->maback;
+ sigma->vadj--;
+ if (!sigma->vadj)
+ {
+ sigma->cgadispon = 1;
+ sigma->ma = sigma->maback = (sigma->crtc[13] | (sigma->crtc[12] << 8)) & 0x3fff;
+ sigma->sc = 0;
+ }
+ }
+ else if (sigma->sc == sigma->crtc[9])
+ {
+ sigma->maback = sigma->ma;
+ sigma->sc = 0;
+ oldvc = sigma->vc;
+ sigma->vc++;
+ sigma->vc &= 127;
+
+ if (sigma->vc == sigma->crtc[6])
+ sigma->cgadispon = 0;
+
+ if (oldvc == sigma->crtc[4])
+ {
+ sigma->vc = 0;
+ sigma->vadj = sigma->crtc[5];
+ if (!sigma->vadj) sigma->cgadispon = 1;
+ if (!sigma->vadj) sigma->ma = sigma->maback = (sigma->crtc[13] | (sigma->crtc[12] << 8)) & 0x3fff;
+ if ((sigma->crtc[10] & 0x60) == 0x20) sigma->cursoron = 0;
+ else sigma->cursoron = sigma->cgablink & 8;
+ }
+
+ if (sigma->vc == sigma->crtc[7])
+ {
+ sigma->cgadispon = 0;
+ sigma->displine = 0;
+ sigma->vsynctime = 16;
+ if (sigma->crtc[7])
+ {
+ if (sigma->sigmamode & MODE_80COLS)
+ x = (sigma->crtc[1] << 4) + 16;
+ else
+ x = (sigma->crtc[1] << 5) + 16;
+ sigma->lastline++;
+ if (x != xsize || (sigma->lastline - sigma->firstline) != ysize)
+ {
+ xsize = x;
+ ysize = sigma->lastline - sigma->firstline;
+// pclog("sigma: xsize := %d ysize := %d\n", xsize, ysize);
+ if (xsize < 64) xsize = 656;
+ if (ysize < 32) ysize = 200;
+ updatewindowsize(xsize, ysize + 8);
+ }
+
+ video_blit_memtoscreen(0, sigma->firstline - 4, 0, (sigma->lastline - sigma->firstline) + 8, xsize, (sigma->lastline - sigma->firstline) + 8);
+ frames++;
+
+ video_res_x = xsize - 16;
+ video_res_y = ysize;
+ if (sigma->sigmamode & MODE_GRAPHICS)
+ {
+ if (sigma->sigmamode & (MODE_HRGFX | MODE_640x400))
+ {
+ video_bpp = 1;
+ }
+ else
+ {
+ video_res_x /= 2;
+ video_bpp = 2;
+ }
+ }
+ else if (sigma->sigmamode & MODE_80COLS)
+ {
+/* 80-column text */
+ video_res_x /= 8;
+ video_res_y /= sigma->crtc[9] + 1;
+ video_bpp = 0;
+ }
+ else
+ {
+/* 40-column text */
+ video_res_x /= 16;
+ video_res_y /= sigma->crtc[9] + 1;
+ video_bpp = 0;
+ }
+ }
+ sigma->firstline = 1000;
+ sigma->lastline = 0;
+ sigma->cgablink++;
+ sigma->oddeven ^= 1;
+ }
+ }
+ else
+ {
+ sigma->sc++;
+ sigma->sc &= 31;
+ sigma->ma = sigma->maback;
+ }
+ if (sigma->cgadispon)
+ sigma->sigmastat &= ~STATUS_RETR_H;
+ if ((sigma->sc == (sigma->crtc[10] & 31) || ((sigma->crtc[8] & 3) == 3 && sigma->sc == ((sigma->crtc[10] & 31) >> 1))))
+ sigma->con = 1;
+ }
+}
+
+
+
+
+void *sigma_init()
+{
+ int display_type, contrast;
+ sigma_t *sigma = malloc(sizeof(sigma_t));
+ memset(sigma, 0, sizeof(sigma_t));
+
+ display_type = device_get_config_int("display_type");
+ contrast = device_get_config_int("contrast");
+ sigma->enable_nmi = device_get_config_int("enable_nmi");
+
+ loadfont("sigma400_font.rom", 7);
+ rom_init(&sigma->bios_rom, "sigma400_bios.rom", 0xC0000, 0x2000,
+ 0x1FFF, 0, MEM_MAPPING_EXTERNAL);
+ /* The BIOS ROM is overlaid by RAM, so remove its default mapping
+ * and access it through sigma_bread() / sigma_bwrite() below */
+ mem_mapping_disable(&sigma->bios_rom.mapping);
+
+ sigma->vram = malloc(0x8000 * 4);
+
+ timer_add(&sigma->timer, sigma_poll, sigma, 1);
+ mem_mapping_add(&sigma->mapping, 0xb8000, 0x08000,
+ sigma_read, NULL, NULL,
+ sigma_write, NULL, NULL,
+ NULL, MEM_MAPPING_EXTERNAL, sigma);
+ mem_mapping_add(&sigma->bios_ram, 0xC1800, 0x0800,
+ sigma_bread, NULL, NULL,
+ sigma_bwrite, NULL, NULL,
+ sigma->bios_rom.rom, MEM_MAPPING_EXTERNAL, sigma);
+ io_sethandler(0x03d0, 0x0010,
+ sigma_in, NULL, NULL,
+ sigma_out, NULL, NULL, sigma);
+ io_sethandler(0x02d0, 0x0010,
+ sigma_in, NULL, NULL,
+ sigma_out, NULL, NULL, sigma);
+
+ /* Start with ROM paged in, BIOS RAM paged out */
+ sigma->rom_paged = 0x80;
+
+ cgapal_rebuild(display_type, contrast);
+
+ if (sigma->enable_nmi)
+ {
+ sigma->sigmastat = STATUS_LPEN_T;
+ }
+ return sigma;
+}
+
+void sigma_close(void *p)
+{
+ sigma_t *sigma = (sigma_t *)p;
+
+ free(sigma->vram);
+ free(sigma);
+}
+
+void sigma_speed_changed(void *p)
+{
+ sigma_t *sigma = (sigma_t *)p;
+
+ sigma_recalctimings(sigma);
+}
+
+device_config_t sigma_config[] =
+{
+ {
+ .name = "display_type",
+ .description = "Display type",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "RGB",
+ .value = DISPLAY_RGB
+ },
+ {
+ .description = "RGB (no brown)",
+ .value = DISPLAY_RGB_NO_BROWN
+ },
+ {
+ .description = "Green Monochrome",
+ .value = DISPLAY_GREEN
+ },
+ {
+ .description = "Amber Monochrome",
+ .value = DISPLAY_AMBER
+ },
+ {
+ .description = "White Monochrome",
+ .value = DISPLAY_WHITE
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = DISPLAY_RGB
+ },
+ {
+ .name = "enable_nmi",
+ .description = "Enable NMI for CGA emulation",
+ .type = CONFIG_BINARY,
+ .default_int = 1
+ },
+ {
+ .name = "contrast",
+ .description = "Alternate monochrome contrast",
+ .type = CONFIG_BINARY,
+ .default_int = 0
+ },
+ {
+ .type = -1
+ }
+};
+
+device_t sigma_device =
+{
+ "Sigma Color 400",
+ 0,
+ sigma_init,
+ sigma_close,
+ NULL,
+ sigma_speed_changed,
+ NULL,
+ NULL,
+ sigma_config
+};
diff --git a/src/vid_sigma.h b/src/vid_sigma.h
new file mode 100644
index 0000000..f59088e
--- /dev/null
+++ b/src/vid_sigma.h
@@ -0,0 +1,2 @@
+extern device_t sigma_device;
+
diff --git a/src/vid_svga.c b/src/vid_svga.c
index 40e0e78..c41528c 100644
--- a/src/vid_svga.c
+++ b/src/vid_svga.c
@@ -53,6 +53,8 @@ void svga_out(uint16_t addr, uint8_t val, void *p)
}
else
{
+ if ((svga->attraddr == 0x13) && (svga->attrregs[0x13] != val))
+ svga->fullchange = changeframecount;
svga->attrregs[svga->attraddr & 31] = val;
if (svga->attraddr < 16)
svga->fullchange = changeframecount;
@@ -114,7 +116,8 @@ void svga_out(uint16_t addr, uint8_t val, void *p)
case 4:
svga->chain2_write = !(val & 4);
svga->chain4 = val & 8;
- svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4;
+ svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) &&
+ ((svga->chain4 && svga->packed_chain4) || svga->fb_only);
break;
}
break;
@@ -199,7 +202,8 @@ void svga_out(uint16_t addr, uint8_t val, void *p)
case 7: svga->colournocare=val; break;
}
svga->gdcreg[svga->gdcaddr & 15] = val;
- svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4;
+ svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) &&
+ ((svga->chain4 && svga->packed_chain4) || svga->fb_only);
if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1))
svga_recalctimings(svga);
break;
@@ -334,7 +338,11 @@ void svga_recalctimings(svga_t *svga)
svga->interlace = 0;
- svga->ma_latch = (svga->crtc[0xc] << 8) | svga->crtc[0xd];
+ svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
+ svga->ca_adj = 0;
+
+ svga->rowcount = svga->crtc[9] & 31;
+ svga->linedbl = svga->crtc[9] & 0x80;
svga->hdisp_time = svga->hdisp;
svga->render = svga_render_blank;
@@ -414,15 +422,14 @@ void svga_recalctimings(svga_t *svga)
// pclog("svga_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", svga_render, svga_render_text_40, svga_render_text_80, svga_render_8bpp_lowres, svga_render_8bpp_highres, svga_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8);
- svga->linedbl = svga->crtc[9] & 0x80;
- svga->rowcount = svga->crtc[9] & 31;
+ svga->char_width = (svga->seqregs[1] & 1) ? 8 : 9;
if (svga->recalctimings_ex)
svga->recalctimings_ex(svga);
if (svga->vblankstart < svga->dispend)
svga->dispend = svga->vblankstart;
- crtcconst = (svga->seqregs[1] & 1) ? (svga->clock * 8.0) : (svga->clock * 9.0);
+ crtcconst = svga->clock * svga->char_width;
disptime = svga->htotal;
_dispontime = svga->hdisp_time;
@@ -439,6 +446,8 @@ void svga_recalctimings(svga_t *svga)
svga->dispontime = TIMER_USEC;
if (svga->dispofftime < TIMER_USEC)
svga->dispofftime = TIMER_USEC;
+
+ svga_recalc_remap_func(svga);
/* printf("SVGA horiz total %i display end %i vidclock %f\n",svga->crtc[0],svga->crtc[1],svga->clock);
printf("SVGA vert total %i display end %i max row %i vsync %i\n",svga->vtotal,svga->dispend,(svga->crtc[9]&31)+1,svga->vsyncstart);
printf("total %f on %i cycles off %i cycles frame %i sec %i %02X\n",disptime*crtcconst,svga->dispontime,svga->dispofftime,(svga->dispontime+svga->dispofftime)*svga->vtotal,(svga->dispontime+svga->dispofftime)*svga->vtotal*70,svga->seqregs[1]);
@@ -580,15 +589,29 @@ void svga_poll(void *p)
svga->ma = svga->maback;
}
}
+ svga->hsync_divisor = !svga->hsync_divisor;
+
+ if (svga->hsync_divisor && (svga->crtc[0x17] & 4))
+ return;
+
svga->vc++;
svga->vc &= 2047;
if (svga->vc == svga->split)
{
-// pclog("VC split\n");
- svga->ma = svga->maback = 0;
- if (svga->attrregs[0x10] & 0x20)
- svga->scrollcache = 0;
+ int ret = 1;
+
+ if (svga->line_compare)
+ ret = svga->line_compare(svga);
+
+ if (ret)
+ {
+// pclog("VC split\n");
+ svga->ma = svga->maback = 0;
+ svga->sc = 0;
+ if (svga->attrregs[0x10] & 0x20)
+ svga->scrollcache = 0;
+ }
}
if (svga->vc == svga->dispend)
{
@@ -643,43 +666,53 @@ void svga_poll(void *p)
if (svga->interlace && svga->oddeven) svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1);
else svga->ma = svga->maback = svga->ma_latch;
- svga->ca = (svga->crtc[0xe] << 8) | svga->crtc[0xf];
+ svga->ca = ((svga->crtc[0xe] << 8) | svga->crtc[0xf]) + svga->ca_adj;
svga->ma <<= 2;
svga->maback <<= 2;
svga->ca <<= 2;
- svga->video_res_x = wx;
- svga->video_res_y = wy + 1;
-// pclog("%i %i %i\n", svga->video_res_x, svga->video_res_y, svga->lowres);
- if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) /*Text mode*/
+ if (!svga->video_res_override)
{
- svga->video_res_x /= (svga->seqregs[1] & 1) ? 8 : 9;
- svga->video_res_y /= (svga->crtc[9] & 31) + 1;
- svga->video_bpp = 0;
- }
- else
- {
- if (svga->crtc[9] & 0x80)
- svga->video_res_y /= 2;
- if (!(svga->crtc[0x17] & 2))
- svga->video_res_y *= 4;
- else if (!(svga->crtc[0x17] & 1))
- svga->video_res_y *= 2;
- svga->video_res_y /= (svga->crtc[9] & 31) + 1;
- if (svga->lowres)
- svga->video_res_x /= 2;
+ svga->video_res_x = wx;
+ svga->video_res_y = wy + 1;
- switch (svga->gdcreg[5] & 0x60)
+ if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) /*Text mode*/
{
- case 0x00: svga->video_bpp = 4; break;
- case 0x20: svga->video_bpp = 2; break;
- case 0x40: case 0x60: svga->video_bpp = svga->bpp; break;
+ svga->video_res_x /= svga->char_width;
+ svga->video_res_y /= (svga->crtc[9] & 31) + 1;
+ svga->video_bpp = 0;
+ }
+ else
+ {
+ if (svga->crtc[9] & 0x80)
+ svga->video_res_y /= 2;
+ if (!(svga->crtc[0x17] & 2))
+ svga->video_res_y *= 4;
+ else if (!(svga->crtc[0x17] & 1))
+ svga->video_res_y *= 2;
+ svga->video_res_y /= (svga->crtc[9] & 31) + 1;
+ if (svga->render == svga_render_8bpp_lowres ||
+ svga->render == svga_render_15bpp_lowres ||
+ svga->render == svga_render_16bpp_lowres ||
+ svga->render == svga_render_24bpp_lowres ||
+ svga->render == svga_render_32bpp_lowres)
+ svga->video_res_x /= 2;
+
+ switch (svga->gdcreg[5] & 0x60)
+ {
+ case 0x00: svga->video_bpp = 4; break;
+ case 0x20: svga->video_bpp = 2; break;
+ case 0x40: case 0x60: svga->video_bpp = svga->bpp; break;
+ }
}
}
// if (svga_interlace && oddeven) ma=maback=ma+(svga_rowoffset<<2);
// pclog("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,svga_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], svga_interlace, oddeven);
+
+ if (svga->vsync_callback)
+ svga->vsync_callback(svga);
}
if (svga->vc == svga->vtotal)
{
@@ -742,13 +775,14 @@ int svga_init(svga_t *svga, void *p, int memsize,
svga->vram_display_mask = memsize - 1;
svga->vram_mask = memsize - 1;
svga->decode_mask = 0x7fffff;
- svga->changedvram = malloc(/*(memsize >> 12) << 1*/0x800000 >> 12);
+ svga->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);
svga->recalctimings_ex = recalctimings_ex;
svga->video_in = video_in;
svga->video_out = video_out;
svga->hwcursor_draw = hwcursor_draw;
svga->overlay_draw = overlay_draw;
svga->hwcursor.ysize = 64;
+ svga->ksc5601_english_font_type = 0;
// _svga_recalctimings(svga);
mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, MEM_MAPPING_EXTERNAL, svga);
@@ -786,11 +820,17 @@ void svga_write(uint32_t addr, uint8_t val, void *p)
addr += svga->write_bank;
if (!(svga->gdcreg[6] & 1)) svga->fullchange=2;
- if (svga->chain4 || svga->fb_only)
+ if ((svga->chain4 && svga->packed_chain4) || svga->fb_only)
{
writemask2=1<<(addr&3);
addr&=~3;
}
+ else if (svga->chain4)
+ {
+ writemask2 = 1 << (addr & 3);
+ addr &= ~3;
+ addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
+ }
else if (svga->chain2_write)
{
writemask2 &= ~0xa;
@@ -966,7 +1006,7 @@ uint8_t svga_read(uint32_t addr, void *p)
cycles -= video_timing_read_b;
cycles_lost += video_timing_read_b;
-
+
egareads++;
// pclog("Readega %06X ",addr);
@@ -977,13 +1017,23 @@ uint8_t svga_read(uint32_t addr, void *p)
// pclog("%05X %i %04X:%04X %02X %02X %i\n",addr,svga->chain4,CS,pc, vram[addr & 0x7fffff], vram[(addr << 2) & 0x7fffff], svga->readmode);
// pclog("%i\n", svga->readmode);
- if (svga->chain4 || svga->fb_only)
+ if ((svga->chain4 && svga->packed_chain4) || svga->fb_only)
{
addr &= svga->decode_mask;
if (addr >= svga->vram_max)
return 0xff;
+ latch_addr = addr & svga->vram_mask & ~3;
+ svga->la = svga->vram[latch_addr];
+ svga->lb = svga->vram[latch_addr | 0x1];
+ svga->lc = svga->vram[latch_addr | 0x2];
+ svga->ld = svga->vram[latch_addr | 0x3];
return svga->vram[addr & svga->vram_mask];
}
+ else if (svga->chain4)
+ {
+ readplane = addr & 3;
+ addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
+ }
else if (svga->chain2_read)
{
readplane = (readplane & 2) | (addr & 1);
@@ -1030,7 +1080,6 @@ uint8_t svga_read(uint32_t addr, void *p)
return ~(temp | temp2 | temp3 | temp4);
}
//pclog("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane);
-
return svga->vram[addr | readplane];
}
@@ -1048,11 +1097,16 @@ void svga_write_linear(uint32_t addr, uint8_t val, void *p)
if (svga_output) pclog("Write LFB %08X %02X ", addr, val);
if (!(svga->gdcreg[6] & 1))
svga->fullchange = 2;
- if (svga->chain4 || svga->fb_only)
+ if ((svga->chain4 && svga->packed_chain4) || svga->fb_only)
{
writemask2=1<<(addr&3);
addr&=~3;
}
+ else if (svga->chain4)
+ {
+ writemask2 = 1 << (addr & 3);
+ addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
+ }
else if (svga->chain2_write)
{
writemask2 &= ~0xa;
@@ -1221,19 +1275,25 @@ uint8_t svga_read_linear(uint32_t addr, void *p)
svga_t *svga = (svga_t *)p;
uint8_t temp, temp2, temp3, temp4;
int readplane = svga->readplane;
+ uint32_t latch_addr = (addr << 2) & svga->decode_mask;
cycles -= video_timing_read_b;
cycles_lost += video_timing_read_b;
egareads++;
- if (svga->chain4 || svga->fb_only)
+ if ((svga->chain4 && svga->packed_chain4) || svga->fb_only)
{
addr &= svga->decode_mask;
if (addr >= svga->vram_max)
return 0xff;
return svga->vram[addr & svga->vram_mask];
}
+ else if (svga->chain4)
+ {
+ readplane = addr & 3;
+ addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff);
+ }
else if (svga->chain2_read)
{
readplane = (readplane & 2) | (addr & 1);
@@ -1241,19 +1301,30 @@ uint8_t svga_read_linear(uint32_t addr, void *p)
addr <<= 2;
}
else
+ {
addr<<=2;
+ }
addr &= svga->decode_mask;
+ if (latch_addr >= svga->vram_max)
+ {
+ svga->la = svga->lb = svga->lc = svga->ld = 0xff;
+ }
+ else
+ {
+ latch_addr &= svga->vram_mask;
+ svga->la = svga->vram[latch_addr];
+ svga->lb = svga->vram[latch_addr | 0x1];
+ svga->lc = svga->vram[latch_addr | 0x2];
+ svga->ld = svga->vram[latch_addr | 0x3];
+ }
+
if (addr >= svga->vram_max)
return 0xff;
addr &= svga->vram_mask;
- svga->la = svga->vram[addr];
- svga->lb = svga->vram[addr | 0x1];
- svga->lc = svga->vram[addr | 0x2];
- svga->ld = svga->vram[addr | 0x3];
if (svga->readmode)
{
temp = svga->la;
@@ -1293,7 +1364,10 @@ void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga)
if (xsize<64) xsize=656;
if (ysize<32) ysize=200;
- updatewindowsize(xsize,ysize);
+ if (svga->vertical_linedbl)
+ updatewindowsize(xsize,ysize*2);
+ else
+ updatewindowsize(xsize,ysize);
}
if (vid_resize)
{
diff --git a/src/vid_svga.h b/src/vid_svga.h
index 0c44fff..f8fb48b 100644
--- a/src/vid_svga.h
+++ b/src/vid_svga.h
@@ -50,7 +50,7 @@ typedef struct svga_t
int set_reset_disabled;
uint8_t egapal[16];
- uint32_t pallook[256];
+ uint32_t pallook[512];
PALETTE vgapal;
int ramdac_type;
@@ -60,7 +60,7 @@ typedef struct svga_t
int lowres, interlace;
int linedbl, rowcount;
double clock;
- uint32_t ma_latch;
+ uint32_t ma_latch, ca_adj;
int bpp;
uint64_t dispontime, dispofftime;
@@ -77,6 +77,7 @@ typedef struct svga_t
int linepos, vslines, linecountff, oddeven;
int con, cursoron, blink;
int scrollcache;
+ int char_width;
int firstline, lastline;
int firstline_draw, lastline_draw;
@@ -92,6 +93,8 @@ typedef struct svga_t
int fullchange;
int video_res_x, video_res_y, video_bpp;
+ int video_res_override; /*If clear then SVGA code will set above variables, if
+ set then card code will*/
int frames, fps;
struct
@@ -123,10 +126,38 @@ typedef struct svga_t
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;
+ uint8_t ksc5601_udc_area_msb[2];
+ int ksc5601_swap_mode;
+ uint16_t ksc5601_english_font_type;
+
+ int vertical_linedbl;
+
+ /*Used to implement CRTC[0x17] bit 2 hsync divisor*/
+ int hsync_divisor;
+
+ /*Tseng-style chain4 mode - CRTC dword mode is the same as byte mode, chain4
+ addresses are shifted to match*/
+ int packed_chain4;
+
+ /*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/
+ int force_dword_mode;
+
+ int remap_required;
+ uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr);
} svga_t;
extern int svga_init(svga_t *svga, void *p, int memsize,
diff --git a/src/vid_svga_render.c b/src/vid_svga_render.c
index 1deb874..f07892b 100644
--- a/src/vid_svga_render.c
+++ b/src/vid_svga_render.c
@@ -3,6 +3,14 @@
#include "video.h"
#include "vid_svga.h"
#include "vid_svga_render.h"
+#include "vid_svga_render_remap.h"
+
+void svga_render_null(svga_t *svga)
+{
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+}
void svga_render_blank(svga_t *svga)
{
@@ -40,7 +48,8 @@ void svga_render_text_40(svga_t *svga)
if (svga->fullchange)
{
- uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[32];
+ int offset = ((8 - svga->scrollcache) << 1) + 16;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
int x, xx;
int drawcursor;
uint8_t chr, attr, dat;
@@ -50,9 +59,12 @@ void svga_render_text_40(svga_t *svga)
for (x = 0; x < svga->hdisp; x += xinc)
{
+ uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask;
+
drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
- chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask];
- attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
+ chr = svga->vram[addr];
+ attr = svga->vram[addr+1];
+
if (attr & 8) charaddr = svga->charsetb + (chr * 128);
else charaddr = svga->charseta + (chr * 128);
@@ -103,7 +115,8 @@ void svga_render_text_80(svga_t *svga)
if (svga->fullchange)
{
- uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[32];
+ int offset = (8 - svga->scrollcache) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
int x, xx;
int drawcursor;
uint8_t chr, attr, dat;
@@ -113,9 +126,12 @@ void svga_render_text_80(svga_t *svga)
for (x = 0; x < svga->hdisp; x += xinc)
{
+ uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask;
+
drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
- chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask];
- attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
+ chr = svga->vram[addr];
+ attr = svga->vram[addr+1];
+
if (attr & 8) charaddr = svga->charsetb + (chr * 128);
else charaddr = svga->charseta + (chr * 128);
@@ -166,7 +182,8 @@ void svga_render_text_80_ksc5601(svga_t *svga)
if (svga->fullchange)
{
- uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[32];
+ int offset = (8 - svga->scrollcache) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
int x, xx;
int drawcursor;
uint8_t chr, attr, dat, nextchr;
@@ -176,10 +193,12 @@ void svga_render_text_80_ksc5601(svga_t *svga)
for (x = 0; x < svga->hdisp; x += xinc)
{
+ uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask;
+
drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
- chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask];
- nextchr = svga->vram[((svga->ma + 4) << 1) & svga->vram_display_mask];
- attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
+ chr = svga->vram[addr];
+ nextchr = svga->vram[addr + 8];
+ attr = svga->vram[addr + 1];
if (drawcursor)
{
@@ -198,19 +217,29 @@ void svga_render_text_80_ksc5601(svga_t *svga)
}
}
- if(x + xinc < svga->hdisp && (chr & nextchr & 0x80))
+ if(x + xinc < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80))
{
- if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff))
- dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20][svga->sc];
- else
+ if((chr == svga->ksc5601_udc_area_msb[0] || chr == svga->ksc5601_udc_area_msb[1]) && (nextchr > 0xa0 && nextchr < 0xff))
+ dat = fontdatksc5601_user[(chr == svga->ksc5601_udc_area_msb[1] ? 96 : 0) + (nextchr & 0x7F) - 0x20][svga->sc];
+ else if(nextchr & 0x80)
+ {
+ if(svga->ksc5601_swap_mode == 1 && (nextchr > 0xa0 && nextchr < 0xff))
+ {
+ if(chr >= 0x80 && chr < 0x99) chr += 0x30;
+ else if(chr >= 0xB0 && chr < 0xC9) chr -= 0x30;
+ }
dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)][svga->sc];
+ }
+ else
+ dat = 0xFF;
}
else
{
if (attr & 8) charaddr = svga->charsetb + (chr * 128);
else charaddr = svga->charseta + (chr * 128);
- dat = svga->vram[charaddr + (svga->sc << 2)];
+ if ((svga->ksc5601_english_font_type >> 8) == 1) dat = fontdatksc5601[((svga->ksc5601_english_font_type & 0x7F) << 7) | (chr >> 1)][((chr & 1) << 4) | svga->sc];
+ else dat = svga->vram[charaddr + (svga->sc << 2)];
}
if (svga->seqregs[1] & 1)
{
@@ -229,7 +258,7 @@ void svga_render_text_80_ksc5601(svga_t *svga)
svga->ma += 4;
p += xinc;
- if(x + xinc < svga->hdisp && (chr & nextchr & 0x80))
+ if(x + xinc < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80))
{
attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
@@ -250,10 +279,14 @@ void svga_render_text_80_ksc5601(svga_t *svga)
}
}
- if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff))
- dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20][svga->sc + 16];
- else
+ if((chr == svga->ksc5601_udc_area_msb[0] || chr == svga->ksc5601_udc_area_msb[1]) && (nextchr > 0xa0 && nextchr < 0xff))
+ dat = fontdatksc5601_user[(chr == svga->ksc5601_udc_area_msb[1] ? 96 : 0) + (nextchr & 0x7F) - 0x20][svga->sc + 16];
+ else if(nextchr & 0x80)
+ {
dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)][svga->sc + 16];
+ }
+ else
+ dat = 0xFF;
if (svga->seqregs[1] & 1)
{
for (xx = 0; xx < 8; xx++)
@@ -280,11 +313,9 @@ void svga_render_text_80_ksc5601(svga_t *svga)
void svga_render_2bpp_lowres(svga_t *svga)
{
- int changed_offset;
-
- changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
- if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange)
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = ((8 - svga->scrollcache) << 1) + 16;
@@ -296,10 +327,11 @@ void svga_render_2bpp_lowres(svga_t *svga)
for (x = 0; x <= svga->hdisp; x += 16)
{
+ uint32_t addr = svga->remap_func(svga, svga->ma);
uint8_t dat[2];
- dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000];
- dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000 + 1];
+ dat[0] = svga->vram[addr];
+ dat[1] = svga->vram[addr + 1];
svga->ma += 4;
svga->ma &= svga->vram_display_mask;
@@ -319,11 +351,9 @@ void svga_render_2bpp_lowres(svga_t *svga)
void svga_render_2bpp_highres(svga_t *svga)
{
- int changed_offset;
-
- changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
-
- if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - svga->scrollcache) + 24;
@@ -335,30 +365,31 @@ void svga_render_2bpp_highres(svga_t *svga)
for (x = 0; x <= svga->hdisp; x += 8)
{
+ uint32_t addr = svga->remap_func(svga, svga->ma);
uint8_t dat[2];
- dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000];
- dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000 + 1];
+ dat[0] = svga->vram[addr];
+ dat[1] = svga->vram[addr + 1];
svga->ma += 4;
svga->ma &= svga->vram_display_mask;
- p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]];
- p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]];
- p[2] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]];
- p[3] = svga->pallook[svga->egapal[dat[0] & 3]];
- p[4] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]];
- p[5] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]];
- p[6] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]];
- p[7] = svga->pallook[svga->egapal[dat[1] & 3]];
-
- p += 8;
+ *p++ = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]];
+ *p++ = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]];
+ *p++ = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]];
+ *p++ = svga->pallook[svga->egapal[dat[0] & 3]];
+ *p++ = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]];
+ *p++ = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]];
+ *p++ = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]];
+ *p++ = svga->pallook[svga->egapal[dat[1] & 3]];
}
}
}
void svga_render_4bpp_lowres(svga_t *svga)
{
- if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = ((8 - svga->scrollcache) << 1) + 16;
@@ -372,8 +403,9 @@ void svga_render_4bpp_lowres(svga_t *svga)
{
uint8_t edat[4];
uint8_t dat;
+ uint32_t addr = svga->remap_func(svga, svga->ma);
- *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma]);
+ *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[addr]);
svga->ma += 4;
svga->ma &= svga->vram_display_mask;
@@ -397,11 +429,9 @@ void svga_render_4bpp_lowres(svga_t *svga)
void svga_render_4bpp_highres(svga_t *svga)
{
- int changed_offset;
-
- changed_offset = (svga->ma + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
-
- if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - svga->scrollcache) + 24;
@@ -415,32 +445,33 @@ void svga_render_4bpp_highres(svga_t *svga)
{
uint8_t edat[4];
uint8_t dat;
+ uint32_t addr = svga->remap_func(svga, svga->ma);
- *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma | ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]);
+ *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[addr]);
svga->ma += 4;
svga->ma &= svga->vram_display_mask;
dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
- p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
- p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
+ *p++ = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
+ *p++ = svga->pallook[svga->egapal[dat & svga->plane_mask]];
dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
- p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
- p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
+ *p++ = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
+ *p++ = svga->pallook[svga->egapal[dat & svga->plane_mask]];
dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
- p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
- p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
+ *p++ = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
+ *p++ = svga->pallook[svga->egapal[dat & svga->plane_mask]];
dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
- p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
- p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
-
- p += 8;
+ *p++ = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
+ *p++ = svga->pallook[svga->egapal[dat & svga->plane_mask]];
}
}
}
void svga_render_8bpp_lowres(svga_t *svga)
{
- if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - (svga->scrollcache & 6)) + 24;
@@ -450,17 +481,36 @@ void svga_render_8bpp_lowres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- for (x = 0; x <= svga->hdisp; x += 8)
+ if (!svga->remap_required)
{
- uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
-
- p[0] = p[1] = svga->pallook[dat & 0xff];
- p[2] = p[3] = svga->pallook[(dat >> 8) & 0xff];
- p[4] = p[5] = svga->pallook[(dat >> 16) & 0xff];
- p[6] = p[7] = svga->pallook[(dat >> 24) & 0xff];
-
- svga->ma += 4;
- p += 8;
+ for (x = 0; x <= svga->hdisp; x += 8)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
+
+ p[0] = p[1] = svga->pallook[dat & 0xff];
+ p[2] = p[3] = svga->pallook[(dat >> 8) & 0xff];
+ p[4] = p[5] = svga->pallook[(dat >> 16) & 0xff];
+ p[6] = p[7] = svga->pallook[(dat >> 24) & 0xff];
+
+ svga->ma += 4;
+ p += 8;
+ }
+ }
+ else
+ {
+ for (x = 0; x <= svga->hdisp; x += 8)
+ {
+ uint32_t addr = svga->remap_func(svga, svga->ma);
+ uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+
+ p[0] = p[1] = svga->pallook[dat & 0xff];
+ p[2] = p[3] = svga->pallook[(dat >> 8) & 0xff];
+ p[4] = p[5] = svga->pallook[(dat >> 16) & 0xff];
+ p[6] = p[7] = svga->pallook[(dat >> 24) & 0xff];
+
+ svga->ma += 4;
+ p += 8;
+ }
}
svga->ma &= svga->vram_display_mask;
}
@@ -468,41 +518,62 @@ void svga_render_8bpp_lowres(svga_t *svga)
void svga_render_8bpp_highres(svga_t *svga)
{
- if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
- if (svga->firstline_draw == 2000)
+ if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- for (x = 0; x <= svga->hdisp; x += 8)
+ if (!svga->remap_required)
{
- uint32_t dat;
- dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
- p[0] = svga->pallook[dat & 0xff];
- p[1] = svga->pallook[(dat >> 8) & 0xff];
- p[2] = svga->pallook[(dat >> 16) & 0xff];
- p[3] = svga->pallook[(dat >> 24) & 0xff];
+ for (x = 0; x <= svga->hdisp; x += 8)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
+ *p++ = svga->pallook[dat & 0xff];
+ *p++ = svga->pallook[(dat >> 8) & 0xff];
+ *p++ = svga->pallook[(dat >> 16) & 0xff];
+ *p++ = svga->pallook[(dat >> 24) & 0xff];
- dat = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]);
- p[4] = svga->pallook[dat & 0xff];
- p[5] = svga->pallook[(dat >> 8) & 0xff];
- p[6] = svga->pallook[(dat >> 16) & 0xff];
- p[7] = svga->pallook[(dat >> 24) & 0xff];
-
- svga->ma += 8;
- p += 8;
+ dat = *(uint32_t *)(&svga->vram[(svga->ma+4) & svga->vram_display_mask]);
+ *p++ = svga->pallook[dat & 0xff];
+ *p++ = svga->pallook[(dat >> 8) & 0xff];
+ *p++ = svga->pallook[(dat >> 16) & 0xff];
+ *p++ = svga->pallook[(dat >> 24) & 0xff];
+
+ svga->ma += 8;
+ }
}
+ else
+ {
+ for (x = 0; x <= svga->hdisp; x += 4)
+ {
+ uint32_t addr = svga->remap_func(svga, svga->ma);
+ uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+
+ svga->ma += 4;
+
+ *p++ = svga->pallook[dat & 0xff];
+ *p++ = svga->pallook[(dat >> 8) & 0xff];
+ *p++ = svga->pallook[(dat >> 16) & 0xff];
+ *p++ = svga->pallook[(dat >> 24) & 0xff];
+ }
+ }
+
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_15bpp_lowres(svga_t *svga)
{
- if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - (svga->scrollcache & 6)) + 24;
@@ -512,26 +583,44 @@ void svga_render_15bpp_lowres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- for (x = 0; x <= svga->hdisp; x += 4)
+ if (!svga->remap_required)
{
- uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
+ for (x = 0; x <= svga->hdisp; x += 4)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
- p[x] = video_15to32[dat & 0xffff];
- p[x + 1] = video_15to32[dat >> 16];
+ *p++ = video_15to32[dat & 0xffff];
+ *p++ = video_15to32[dat >> 16];
- dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
- p[x] = video_15to32[dat & 0xffff];
- p[x + 1] = video_15to32[dat >> 16];
+ *p++ = video_15to32[dat & 0xffff];
+ *p++ = video_15to32[dat >> 16];
+ }
+ svga->ma += x << 1;
+ }
+ else
+ {
+ for (x = 0; x <= svga->hdisp; x += 2)
+ {
+ uint32_t addr = svga->remap_func(svga, svga->ma);
+ uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+
+ *p++ = video_15to32[dat & 0xffff];
+ *p++ = video_15to32[dat >> 16];
+
+ svga->ma += 4;
+ }
}
- svga->ma += x << 1;
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_15bpp_highres(svga_t *svga)
{
- if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
@@ -541,32 +630,51 @@ void svga_render_15bpp_highres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- for (x = 0; x <= svga->hdisp; x += 8)
+ if (!svga->remap_required)
{
- uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
- p[x] = video_15to32[dat & 0xffff];
- p[x + 1] = video_15to32[dat >> 16];
+ for (x = 0; x <= svga->hdisp; x += 8)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
+ *p++ = video_15to32[dat & 0xffff];
+ *p++ = video_15to32[dat >> 16];
- dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
- p[x + 2] = video_15to32[dat & 0xffff];
- p[x + 3] = video_15to32[dat >> 16];
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
+ *p++ = video_15to32[dat & 0xffff];
+ *p++ = video_15to32[dat >> 16];
- dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
- p[x + 4] = video_15to32[dat & 0xffff];
- p[x + 5] = video_15to32[dat >> 16];
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
+ *p++ = video_15to32[dat & 0xffff];
+ *p++ = video_15to32[dat >> 16];
- dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
- p[x + 6] = video_15to32[dat & 0xffff];
- p[x + 7] = video_15to32[dat >> 16];
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
+ *p++ = video_15to32[dat & 0xffff];
+ *p++ = video_15to32[dat >> 16];
+ }
+
+ svga->ma += x << 1;
+ }
+ else
+ {
+ for (x = 0; x <= svga->hdisp; x += 2)
+ {
+ uint32_t addr = svga->remap_func(svga, svga->ma);
+ uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+
+ *p++ = video_15to32[dat & 0xffff];
+ *p++ = video_15to32[dat >> 16];
+
+ svga->ma += 4;
+ }
}
- svga->ma += x << 1;
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_16bpp_lowres(svga_t *svga)
{
- if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - (svga->scrollcache & 6)) + 24;
@@ -576,26 +684,45 @@ void svga_render_16bpp_lowres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- for (x = 0; x <= svga->hdisp; x += 4)
+ if (!svga->remap_required)
{
- uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
+ for (x = 0; x <= svga->hdisp; x += 4)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
- p[x] = video_16to32[dat & 0xffff];
- p[x + 1] = video_16to32[dat >> 16];
+ *p++ = video_16to32[dat & 0xffff];
+ *p++ = video_16to32[dat >> 16];
- dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
- p[x] = video_16to32[dat & 0xffff];
- p[x + 1] = video_16to32[dat >> 16];
+ *p++ = video_16to32[dat & 0xffff];
+ *p++ = video_16to32[dat >> 16];
+ }
+ svga->ma += x << 1;
}
- svga->ma += x << 1;
+ else
+ {
+ for (x = 0; x <= svga->hdisp; x += 2)
+ {
+ uint32_t addr = svga->remap_func(svga, svga->ma);
+ uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+
+ *p++ = video_16to32[dat & 0xffff];
+ *p++ = video_16to32[dat >> 16];
+
+ svga->ma += 4;
+ }
+ }
+ svga->ma += x << 1;
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_16bpp_highres(svga_t *svga)
{
- if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
@@ -605,55 +732,106 @@ void svga_render_16bpp_highres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- for (x = 0; x <= svga->hdisp; x += 8)
+ if (!svga->remap_required)
{
- uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
- p[x] = video_16to32[dat & 0xffff];
- p[x + 1] = video_16to32[dat >> 16];
-
- dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
- p[x + 2] = video_16to32[dat & 0xffff];
- p[x + 3] = video_16to32[dat >> 16];
+ for (x = 0; x <= svga->hdisp; x += 8)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
+ *p++ = video_16to32[dat & 0xffff];
+ *p++ = video_16to32[dat >> 16];
- dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
- p[x + 4] = video_16to32[dat & 0xffff];
- p[x + 5] = video_16to32[dat >> 16];
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
+ *p++ = video_16to32[dat & 0xffff];
+ *p++ = video_16to32[dat >> 16];
- dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
- p[x + 6] = video_16to32[dat & 0xffff];
- p[x + 7] = video_16to32[dat >> 16];
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
+ *p++ = video_16to32[dat & 0xffff];
+ *p++ = video_16to32[dat >> 16];
+
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
+ *p++ = video_16to32[dat & 0xffff];
+ *p++ = video_16to32[dat >> 16];
+ }
+
+ svga->ma += x << 1;
+ }
+ else
+ {
+ for (x = 0; x <= svga->hdisp; x += 2)
+ {
+ uint32_t addr = svga->remap_func(svga, svga->ma);
+ uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+
+ *p++ = video_16to32[dat & 0xffff];
+ *p++ = video_16to32[dat >> 16];
+
+ svga->ma += 4;
+ }
}
- svga->ma += x << 1;
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_24bpp_lowres(svga_t *svga)
{
- int x, offset;
- uint32_t fg;
-
- if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
+ int x;
+ int offset = (8 - (svga->scrollcache & 6)) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- offset = (8 - (svga->scrollcache & 6)) + 24;
-
- for (x = 0; x <= svga->hdisp; x++)
+ if (!svga->remap_required)
{
- fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
- svga->ma += 3;
- svga->ma &= svga->vram_display_mask;
- ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg;
+ for (x = 0; x <= svga->hdisp; x++)
+ {
+ uint32_t dat0 = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
+ uint32_t dat1 = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]);
+ uint32_t dat2 = *(uint32_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]);
+
+ p[0] = p[1] = dat0 & 0xffffff;
+ p[2] = p[3] = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
+ p[4] = p[5] = (dat1 >> 16) | ((dat2 & 0xff) << 16);
+ p[6] = p[7] = dat2 >> 8;
+
+ svga->ma += 12;
+ }
+ }
+ else
+ {
+ for (x = 0; x <= svga->hdisp; x += 4)
+ {
+ uint32_t dat0, dat1, dat2;
+ uint32_t addr;
+
+ addr = svga->remap_func(svga, svga->ma);
+ dat0 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+ addr = svga->remap_func(svga, svga->ma + 4);
+ dat1 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+ addr = svga->remap_func(svga, svga->ma + 8);
+ dat2 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+
+ p[0] = p[1] = dat0 & 0xffffff;
+ p[2] = p[3] = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
+ p[4] = p[5] = (dat1 >> 16) | ((dat2 & 0xff) << 16);
+ p[6] = p[7] = dat2 >> 8;
+
+ svga->ma += 12;
+ }
}
}
}
void svga_render_24bpp_highres(svga_t *svga)
{
- if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
@@ -663,21 +841,43 @@ void svga_render_24bpp_highres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- for (x = 0; x <= svga->hdisp; x += 4)
+ if (!svga->remap_required)
{
- uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
- p[x] = dat & 0xffffff;
-
- dat = *(uint32_t *)(&svga->vram[(svga->ma + 3) & svga->vram_display_mask]);
- p[x + 1] = dat & 0xffffff;
-
- dat = *(uint32_t *)(&svga->vram[(svga->ma + 6) & svga->vram_display_mask]);
- p[x + 2] = dat & 0xffffff;
-
- dat = *(uint32_t *)(&svga->vram[(svga->ma + 9) & svga->vram_display_mask]);
- p[x + 3] = dat & 0xffffff;
-
- svga->ma += 12;
+ for (x = 0; x <= svga->hdisp; x += 4)
+ {
+ uint32_t dat0 = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
+ uint32_t dat1 = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]);
+ uint32_t dat2 = *(uint32_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]);
+
+ *p++ = dat0 & 0xffffff;
+ *p++ = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
+ *p++ = (dat1 >> 16) | ((dat2 & 0xff) << 16);
+ *p++ = dat2 >> 8;
+
+ svga->ma += 12;
+ }
+ }
+ else
+ {
+ for (x = 0; x <= svga->hdisp; x += 4)
+ {
+ uint32_t dat0, dat1, dat2;
+ uint32_t addr;
+
+ addr = svga->remap_func(svga, svga->ma);
+ dat0 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+ addr = svga->remap_func(svga, svga->ma + 4);
+ dat1 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+ addr = svga->remap_func(svga, svga->ma + 8);
+ dat2 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+
+ *p++ = dat0 & 0xffffff;
+ *p++ = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
+ *p++ = (dat1 >> 16) | ((dat2 & 0xff) << 16);
+ *p++ = dat2 >> 8;
+
+ svga->ma += 12;
+ }
}
svga->ma &= svga->vram_display_mask;
}
@@ -685,24 +885,40 @@ void svga_render_24bpp_highres(svga_t *svga)
void svga_render_32bpp_lowres(svga_t *svga)
{
- int x, offset;
- uint32_t fg;
-
- if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
+ int x;
+ int offset = (8 - (svga->scrollcache & 6)) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- offset = (8 - (svga->scrollcache & 6)) + 24;
-
- for (x = 0; x <= svga->hdisp; x++)
+ if (!svga->remap_required)
{
- fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
- svga->ma += 4;
- svga->ma &= svga->vram_display_mask;
- ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg;
+ for (x = 0; x <= svga->hdisp; x++)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
+ *p++ = dat & 0xffffff;
+ *p++ = dat & 0xffffff;
+ }
+ svga->ma += x*4;
}
+ else
+ {
+ for (x = 0; x <= svga->hdisp; x++)
+ {
+ uint32_t addr = svga->remap_func(svga, svga->ma);
+ uint32_t dat = *(uint32_t *)(&svga->vram[addr]);
+ *p++ = dat & 0xffffff;
+ *p++ = dat & 0xffffff;
+ svga->ma += 4;
+ }
+ }
+ svga->ma &= svga->vram_display_mask;
}
}
@@ -710,7 +926,9 @@ void svga_render_32bpp_lowres(svga_t *svga)
91%*/
void svga_render_32bpp_highres(svga_t *svga)
{
- if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
@@ -720,56 +938,102 @@ void svga_render_32bpp_highres(svga_t *svga)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- for (x = 0; x <= svga->hdisp; x++)
+ if (!svga->remap_required)
{
- uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
- p[x] = dat & 0xffffff;
+ for (x = 0; x <= svga->hdisp; x++)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
+ *p++ = dat & 0xffffff;
+ }
+ svga->ma += x*4;
}
- svga->ma += 4;
+ else
+ {
+ for (x = 0; x <= svga->hdisp; x++)
+ {
+ uint32_t addr = svga->remap_func(svga, svga->ma);
+ uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+ *p++ = dat & 0xffffff;
+ svga->ma += 4;
+ }
+ }
+
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_ABGR8888_highres(svga_t *svga)
{
- if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
-
- if (svga->firstline_draw == 2000)
+
+ if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- for (x = 0; x <= svga->hdisp; x++)
+ if (!svga->remap_required)
{
- uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
- p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
+ for (x = 0; x <= svga->hdisp; x++)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
+ *p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
+ }
+ svga->ma += x*4;
}
- svga->ma += 4;
+ else
+ {
+ for (x = 0; x <= svga->hdisp; x++)
+ {
+ uint32_t addr = svga->remap_func(svga, svga->ma);
+ uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+ *p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
+ svga->ma += 4;
+ }
+ }
+
svga->ma &= svga->vram_display_mask;
}
}
void svga_render_RGBA8888_highres(svga_t *svga)
{
- if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange)
+ uint32_t changed_addr = svga->remap_func(svga, svga->ma);
+
+ if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
{
int x;
int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
-
- if (svga->firstline_draw == 2000)
+
+ if (svga->firstline_draw == 2000)
svga->firstline_draw = svga->displine;
svga->lastline_draw = svga->displine;
- for (x = 0; x <= svga->hdisp; x++)
+ if (!svga->remap_required)
{
- uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
- p[x] = dat >> 8;
+ for (x = 0; x <= svga->hdisp; x++)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
+ *p++ = dat >> 8;
+ }
+ svga->ma += x*4;
}
- svga->ma += 4;
+ else
+ {
+ for (x = 0; x <= svga->hdisp; x++)
+ {
+ uint32_t addr = svga->remap_func(svga, svga->ma);
+ uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+ *p++ = dat >> 8;
+ svga->ma += 4;
+ }
+ }
+
svga->ma &= svga->vram_display_mask;
}
}
diff --git a/src/vid_svga_render.h b/src/vid_svga_render.h
index fb88e8d..bb3b3c1 100644
--- a/src/vid_svga_render.h
+++ b/src/vid_svga_render.h
@@ -9,6 +9,9 @@ extern int scrollcache;
extern uint8_t edatlookup[4][4];
+void svga_recalc_remap_func(svga_t *svga);
+
+void svga_render_null(svga_t *svga);
void svga_render_blank(svga_t *svga);
void svga_render_text_40(svga_t *svga);
void svga_render_text_80(svga_t *svga);
diff --git a/src/vid_svga_render_remap.h b/src/vid_svga_render_remap.h
new file mode 100644
index 0000000..189f846
--- /dev/null
+++ b/src/vid_svga_render_remap.h
@@ -0,0 +1,129 @@
+/*Variables :
+ byte/word/doubleword mode
+ word has MA13/MA15->MA0
+ ET4000 treats doubleword as byte
+ row 0 -> MA13
+ row 1 -> MA14
+*/
+
+//S3 - enhanced mode mappings CR31.3 can force doubleword mode
+//Cirrus Logic handles SVGA writes seperately
+//S3, CL, TGUI blitters need checking
+
+//CL, S3, Mach64, ET4000, Banshee, TGUI all okay
+//Still to check - ViRGE, HT216
+#define VAR_BYTE_MODE (0 << 0)
+#define VAR_WORD_MODE_MA13 (1 << 0)
+#define VAR_WORD_MODE_MA15 (2 << 0)
+#define VAR_DWORD_MODE (3 << 0)
+#define VAR_MODE_MASK (3 << 0)
+#define VAR_ROW0_MA13 (1 << 2)
+#define VAR_ROW1_MA14 (1 << 3)
+
+#define ADDRESS_REMAP_FUNC(nr) \
+ static uint32_t address_remap_func_ ## nr(svga_t *svga, uint32_t in_addr) \
+ { \
+ uint32_t out_addr; \
+ \
+ switch (nr & VAR_MODE_MASK) \
+ { \
+ case VAR_BYTE_MODE: \
+ out_addr = in_addr; \
+ break; \
+ \
+ case VAR_WORD_MODE_MA13: \
+ out_addr = ((in_addr << 1) & 0x1fff8) | \
+ ((in_addr >> 13) & 0x4) | \
+ (in_addr & ~0x1ffff); \
+ break; \
+ \
+ case VAR_WORD_MODE_MA15: \
+ out_addr = ((in_addr << 1) & 0x1fff8) | \
+ ((in_addr >> 15) & 0x4) | \
+ (in_addr & ~0x1ffff); \
+ break; \
+ \
+ case VAR_DWORD_MODE: \
+ out_addr = ((in_addr << 2) & 0x3fff0) | \
+ ((in_addr >> 14) & 0xc) | \
+ (in_addr & ~0x3ffff); \
+ break; \
+ } \
+ \
+ if (nr & VAR_ROW0_MA13) \
+ out_addr = (out_addr & ~(1 << (13+2))) | \
+ ((svga->sc & 1) ? (1 << (13+2)) : 0); \
+ if (nr & VAR_ROW1_MA14) \
+ out_addr = (out_addr & ~(1 << (14+2))) | \
+ ((svga->sc & 2) ? (1 << (14+2)) : 0); \
+ \
+ return out_addr; \
+ }
+
+ADDRESS_REMAP_FUNC(0)
+ADDRESS_REMAP_FUNC(1)
+ADDRESS_REMAP_FUNC(2)
+ADDRESS_REMAP_FUNC(3)
+ADDRESS_REMAP_FUNC(4)
+ADDRESS_REMAP_FUNC(5)
+ADDRESS_REMAP_FUNC(6)
+ADDRESS_REMAP_FUNC(7)
+ADDRESS_REMAP_FUNC(8)
+ADDRESS_REMAP_FUNC(9)
+ADDRESS_REMAP_FUNC(10)
+ADDRESS_REMAP_FUNC(11)
+ADDRESS_REMAP_FUNC(12)
+ADDRESS_REMAP_FUNC(13)
+ADDRESS_REMAP_FUNC(14)
+ADDRESS_REMAP_FUNC(15)
+
+static uint32_t (*address_remap_funcs[16])(svga_t *svga, uint32_t in_addr) =
+{
+ address_remap_func_0,
+ address_remap_func_1,
+ address_remap_func_2,
+ address_remap_func_3,
+ address_remap_func_4,
+ address_remap_func_5,
+ address_remap_func_6,
+ address_remap_func_7,
+ address_remap_func_8,
+ address_remap_func_9,
+ address_remap_func_10,
+ address_remap_func_11,
+ address_remap_func_12,
+ address_remap_func_13,
+ address_remap_func_14,
+ address_remap_func_15
+};
+
+void svga_recalc_remap_func(svga_t *svga)
+{
+ int func_nr;
+
+ if (svga->fb_only)
+ func_nr = 0;
+ else
+ {
+ if (svga->force_dword_mode)
+ func_nr = VAR_DWORD_MODE;
+ else if (svga->crtc[0x14] & (1 << 6))
+ func_nr = svga->packed_chain4 ? VAR_BYTE_MODE : VAR_DWORD_MODE;
+ else if (svga->crtc[0x17] & (1 << 6))
+ func_nr = VAR_BYTE_MODE;
+ else if (svga->crtc[0x17] & (1 << 5))
+ func_nr = VAR_WORD_MODE_MA15;
+ else
+ func_nr = VAR_WORD_MODE_MA13;
+
+ if (!(svga->crtc[0x17] & (1 << 0)))
+ func_nr |= VAR_ROW0_MA13;
+ if (!(svga->crtc[0x17] & (1 << 1)))
+ func_nr |= VAR_ROW1_MA14;
+ }
+
+// pclog("svga_recalc_remap_func: fb_only=%i chain4=%i packed_chain4=%i crtc[14]=%02x crtc[17]=%02x func_nr=%i\n",
+// svga->fb_only, svga->chain4, svga->packed_chain4, svga->crtc[0x14], svga->crtc[0x17], func_nr);
+ svga->remap_required = (func_nr != 0);
+ svga->remap_func = address_remap_funcs[func_nr];
+}
diff --git a/src/vid_tandy.c b/src/vid_tandy.c
index d2cd49a..1b07f27 100644
--- a/src/vid_tandy.c
+++ b/src/vid_tandy.c
@@ -60,10 +60,10 @@ void tandy_out(uint16_t addr, uint8_t val, void *p)
// pclog("Tandy OUT %04X %02X\n",addr,val);
switch (addr)
{
- case 0x3d4:
+ case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6:
tandy->crtcreg = val & 0x1f;
return;
- case 0x3d5:
+ case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7:
old = tandy->crtc[tandy->crtcreg];
tandy->crtc[tandy->crtcreg] = val & crtcmask[tandy->crtcreg];
if (old != val)
diff --git a/src/vid_tandysl.c b/src/vid_tandysl.c
index 2a521b0..1119f14 100644
--- a/src/vid_tandysl.c
+++ b/src/vid_tandysl.c
@@ -60,10 +60,10 @@ static void tandysl_out(uint16_t addr, uint8_t val, void *p)
// pclog("TandySL OUT %04X %02X\n",addr,val);
switch (addr)
{
- case 0x3d4:
+ case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6:
tandy->crtcreg = val & 0x1f;
return;
- case 0x3d5:
+ case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7:
// pclog("Write CRTC R%02x %02x ",tandy->crtcreg, val);
old = tandy->crtc[tandy->crtcreg];
tandy->crtc[tandy->crtcreg] = val & crtcmask[tandy->crtcreg];
diff --git a/src/vid_tgui9440.c b/src/vid_tgui9440.c
index bb8194c..a42f7e9 100644
--- a/src/vid_tgui9440.c
+++ b/src/vid_tgui9440.c
@@ -470,19 +470,10 @@ void tgui_recalctimings(svga_t *svga)
if (svga->interlace && tgui->type < TGUI_9440)
svga->rowoffset >>= 1;
- if (svga->crtc[0x17] & 4)
- {
- svga->vtotal *= 2;
- svga->dispend *= 2;
- svga->vsyncstart *= 2;
- svga->split *= 2;
- svga->vblankstart *= 2;
- }
-
if (tgui->type >= TGUI_9440)
{
if (svga->miscout & 8)
- svga->clock = cpuclock / (((tgui->clock_n + 8) * 14318180.0) / ((tgui->clock_m + 2) * (1 << tgui->clock_k)));
+ 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;
@@ -493,20 +484,20 @@ void tgui_recalctimings(svga_t *svga)
{
switch (((svga->miscout >> 2) & 3) | ((tgui->newctrl2 << 2) & 4) | ((tgui->newctrl2 >> 3) & 8))
{
- case 0x02: svga->clock = cpuclock/ 44900000.0; break;
- case 0x03: svga->clock = cpuclock/ 36000000.0; break;
- case 0x04: svga->clock = cpuclock/ 57272000.0; break;
- case 0x05: svga->clock = cpuclock/ 65000000.0; break;
- case 0x06: svga->clock = cpuclock/ 50350000.0; break;
- case 0x07: svga->clock = cpuclock/ 40000000.0; break;
- case 0x08: svga->clock = cpuclock/ 88000000.0; break;
- case 0x09: svga->clock = cpuclock/ 98000000.0; break;
- case 0x0a: svga->clock = cpuclock/118800000.0; break;
- case 0x0b: svga->clock = cpuclock/108000000.0; break;
- case 0x0c: svga->clock = cpuclock/ 72000000.0; break;
- case 0x0d: svga->clock = cpuclock/ 77000000.0; break;
- case 0x0e: svga->clock = cpuclock/ 80000000.0; break;
- case 0x0f: svga->clock = cpuclock/ 75000000.0; break;
+ 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)
{
@@ -640,17 +631,34 @@ void tgui_recalcmapping(tgui_t *tgui)
}
}
+/*Remap address for chain-4/doubleword style layout*/
+static inline uint32_t dword_remap(uint32_t in_addr)
+{
+ return ((in_addr << 2) & 0x3fff0) |
+ ((in_addr >> 14) & 0xc) |
+ (in_addr & ~0x3fffc);
+}
+static inline uint32_t dword_remap_w(uint32_t in_addr)
+{
+ return ((in_addr << 2) & 0x1fff8) |
+ ((in_addr >> 14) & 0x6) |
+ (in_addr & ~0x1fffe);
+}
+
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;
+ uint32_t remapped_addr;
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];
+ remapped_addr = dword_remap(svga->hwcursor_latch.addr);
+ dat[0] = (svga->vram[remapped_addr] << 24) | (svga->vram[remapped_addr + 1] << 16) | (svga->vram[remapped_addr + 2] << 8) | svga->vram[remapped_addr + 3];
+ remapped_addr = dword_remap(svga->hwcursor_latch.addr+4);
+ dat[1] = (svga->vram[remapped_addr] << 24) | (svga->vram[remapped_addr + 1] << 16) | (svga->vram[remapped_addr + 2] << 8) | svga->vram[remapped_addr + 3];
for (xx = 0; xx < 32; xx++)
{
if (offset >= svga->hwcursor_latch.x)
@@ -799,7 +807,7 @@ static void *tgui9440_init()
static int tgui9400cxi_available()
{
- return rom_present("9400CXI.VBI");
+ return rom_present("9400CXI.vbi");
}
static int tgui9440_available()
@@ -849,8 +857,13 @@ static uint8_t tgui_ext_linear_read(uint32_t addr, void *p)
return 0xff;
addr &= ~0xf;
+ addr = dword_remap(addr);
+
for (c = 0; c < 16; c++)
- tgui->copy_latch[c] = svga->vram[addr+c];
+ {
+ tgui->copy_latch[c] = svga->vram[addr];
+ addr += ((c & 3) == 3) ? 13 : 1;
+ }
return svga->vram[addr & svga->vram_mask];
}
@@ -880,7 +893,9 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
if (addr >= svga->vram_max)
return;
addr &= svga->vram_mask;
- addr &= ~0x7;
+ addr &= (tgui->ext_gdc_regs[0] & 8) ? ~0xf : ~0x7;
+
+ addr = dword_remap(addr);
svga->changedvram[addr >> 12] = changeframecount;
switch (tgui->ext_gdc_regs[0] & 0xf)
@@ -891,7 +906,7 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
{
if (mask & (1 << c))
*(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[0] : bg[0];
- addr++;
+ addr += (c == 4) ? 13 : 1;
}
break;
@@ -901,7 +916,7 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
{
if (mask & (1 << c))
*(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1];
- addr++;
+ addr += (c == 4) ? 13 : 1;
}
break;
@@ -911,7 +926,7 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
{
if ((val & mask) & (1 << c))
*(uint8_t *)&svga->vram[addr] = fg[0];
- addr++;
+ addr += (c == 4) ? 13 : 1;
}
break;
@@ -921,15 +936,17 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p)
{
if ((val & mask) & (1 << c))
*(uint8_t *)&svga->vram[addr] = fg[(c & 1) ^ 1];
- addr++;
+ addr += (c == 4) ? 13 : 1;
}
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];
+ {
+ *(uint8_t *)&svga->vram[addr] = tgui->copy_latch[c];
+ addr += ((c & 3) == 3) ? 13 : 1;
+ }
break;
}
}
@@ -951,6 +968,8 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
return;
addr &= svga->vram_mask;
addr &= ~0xf;
+
+ addr = dword_remap(addr);
svga->changedvram[addr >> 12] = changeframecount;
val = (val >> 8) | (val << 8);
@@ -963,7 +982,7 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
{
if (mask & (1 << c))
*(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[0] : bg[0];
- addr++;
+ addr += (c & 3) ? 1 : 13;
}
break;
@@ -973,7 +992,7 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
{
if (mask & (1 << c))
*(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1];
- addr++;
+ addr += (c & 3) ? 1 : 13;
}
break;
@@ -983,7 +1002,7 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
{
if ((val & mask) & (1 << c))
*(uint8_t *)&svga->vram[addr] = fg[0];
- addr++;
+ addr += (c & 3) ? 1 : 13;
}
break;
@@ -993,14 +1012,17 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p)
{
if ((val & mask) & (1 << c))
*(uint8_t *)&svga->vram[addr] = fg[(c & 1) ^ 1];
- addr++;
+ addr += (c & 3) ? 1 : 13;
}
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];
+ {
+ *(uint8_t *)&svga->vram[addr] = tgui->copy_latch[c];
+ addr += ((c & 3) == 3) ? 13 : 1;
+ }
break;
}
}
@@ -1053,8 +1075,8 @@ enum
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 READ(addr, dat) if (tgui->accel.bpp == 0) dat = svga->vram[dword_remap(addr) & 0x1fffff]; \
+ else dat = vram_w[dword_remap_w(addr) & 0xfffff];
#define MIX() do \
{ \
@@ -1070,13 +1092,13 @@ enum
#define WRITE(addr, dat) if (tgui->accel.bpp == 0) \
{ \
- svga->vram[addr & 0x1fffff] = dat; \
- svga->changedvram[((addr) & 0x1fffff) >> 12] = changeframecount; \
+ svga->vram[dword_remap(addr) & 0x1fffff] = dat; \
+ svga->changedvram[(dword_remap(addr) & 0x1fffff) >> 12] = changeframecount; \
} \
else \
{ \
- vram_w[addr & 0xfffff] = dat; \
- svga->changedvram[((addr) & 0xfffff) >> 11] = changeframecount; \
+ vram_w[dword_remap_w(addr) & 0xfffff] = dat; \
+ svga->changedvram[(dword_remap_w(addr) & 0xfffff) >> 11] = changeframecount; \
}
void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui)
diff --git a/src/vid_tvga.c b/src/vid_tvga.c
index 9d24c8b..6a42ac4 100644
--- a/src/vid_tvga.c
+++ b/src/vid_tvga.c
@@ -11,6 +11,12 @@
#include "vid_tkd8001_ramdac.h"
#include "vid_tvga.h"
+enum
+{
+ TVGA_8900D = 0x33,
+ TVGA_9000 = 0x23
+};
+
typedef struct tvga_t
{
mem_mapping_t linear_mapping;
@@ -28,6 +34,8 @@ typedef struct tvga_t
int vram_size;
uint32_t vram_mask;
+
+ uint8_t id;
} tvga_t;
static uint8_t crtc_mask[0x40] =
@@ -67,7 +75,7 @@ void tvga_out(uint16_t addr, uint8_t val, void *p)
break;
case 0xd:
if (tvga->oldmode)
- tvga->oldctrl2 = val;
+ tvga->oldctrl2 = val;
else
{
tvga->newctrl2 = val;
@@ -76,7 +84,10 @@ void tvga_out(uint16_t addr, uint8_t val, void *p)
break;
case 0xE:
if (tvga->oldmode)
+ {
tvga->oldctrl1 = val;
+ svga_recalctimings(svga);
+ }
else
{
svga->seqregs[0xe] = val ^ 2;
@@ -88,12 +99,25 @@ void tvga_out(uint16_t addr, uint8_t val, void *p)
break;
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
- tkd8001_ramdac_out(addr, val, &tvga->ramdac, svga);
- return;
+ if (tvga->id != TVGA_9000)
+ {
+ tkd8001_ramdac_out(addr, val, &tvga->ramdac, svga);
+ return;
+ }
+ break;
case 0x3CF:
switch (svga->gdcaddr & 15)
{
+ case 0x6:
+ old = svga->gdcreg[6];
+ svga_out(addr, val, svga);
+ if ((old & 0xc) != 0 && (val & 0xc) == 0)
+ {
+ /*override mask - TVGA supports linear 128k at A0000*/
+ svga->banked_mask = 0x1ffff;
+ }
+ return;
case 0xE:
svga->gdcreg[0xe] = val ^ 2;
tvga->tvga_3d9 = svga->gdcreg[0xe] & 0xf;
@@ -146,6 +170,16 @@ void tvga_out(uint16_t addr, uint8_t val, void *p)
tvga_recalcbanking(tvga);
}
return;
+ case 0x3DB:
+ if (tvga->id == TVGA_8900D)
+ {
+ /*3db appears to be a 4 bit clock select register on 8900D*/
+ svga->miscout = (svga->miscout & ~0x0c) | ((val & 3) << 2);
+ tvga->newctrl2 = (tvga->newctrl2 & ~0x01) | ((val & 4) >> 2);
+ tvga->oldctrl1 = (tvga->oldctrl1 & ~0x10) | ((val & 8) << 1);
+ svga_recalctimings(svga);
+ }
+ break;
}
svga_out(addr, val, svga);
}
@@ -166,7 +200,7 @@ uint8_t tvga_in(uint16_t addr, void *p)
{
// printf("Read Trident ID %04X:%04X %04X\n",CS,pc,readmemw(ss,SP));
tvga->oldmode = 0;
- return 0x33; /*TVGA8900D*/
+ return tvga->id;
}
if ((svga->seqaddr & 0xf) == 0xc)
{
@@ -185,7 +219,9 @@ uint8_t tvga_in(uint16_t addr, void *p)
}
break;
case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
- return tkd8001_ramdac_in(addr, &tvga->ramdac, svga);
+ if (tvga->id != TVGA_9000)
+ return tkd8001_ramdac_in(addr, &tvga->ramdac, svga);
+ break;
case 0x3D4:
return svga->crtcreg;
case 0x3D5:
@@ -217,6 +253,9 @@ static void tvga_recalcbanking(tvga_t *tvga)
void tvga_recalctimings(svga_t *svga)
{
tvga_t *tvga = (tvga_t *)svga->p;
+ int clksel;
+ int high_res_256 = 0;
+
if (!svga->rowoffset) svga->rowoffset = 0x100; /*This is the only sensible way I can see this being handled,
given that TVGA8900D has no overflow bits.
Some sort of overflow is required for 320x200x24 and 1024x768x16*/
@@ -246,18 +285,43 @@ void tvga_recalctimings(svga_t *svga)
if (svga->interlace)
svga->rowoffset >>= 1;
- switch (((svga->miscout >> 2) & 3) | ((tvga->newctrl2 << 2) & 4))
+ if (tvga->id == TVGA_8900D)
+ clksel = ((svga->miscout >> 2) & 3) | ((tvga->newctrl2 & 0x01) << 2) | ((tvga->oldctrl1 & 0x10) >> 1);
+ else
+ clksel = ((svga->miscout >> 2) & 3) | ((tvga->newctrl2 & 0x01) << 2) | ((tvga->newctrl2 & 0x40) >> 3);
+ switch (clksel)
{
- case 2: svga->clock = cpuclock/44900000.0; break;
- case 3: svga->clock = cpuclock/36000000.0; break;
- case 4: svga->clock = cpuclock/57272000.0; break;
- case 5: svga->clock = cpuclock/65000000.0; break;
- case 6: svga->clock = cpuclock/50350000.0; break;
- case 7: svga->clock = cpuclock/40000000.0; break;
+ case 0x2: svga->clock = (cpuclock * (double)(1ull << 32)) / 44900000.0; break;
+ case 0x3: svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; break;
+ case 0x4: svga->clock = (cpuclock * (double)(1ull << 32)) / 57272000.0; break;
+ case 0x5: svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; break;
+ case 0x6: svga->clock = (cpuclock * (double)(1ull << 32)) / 50350000.0; break;
+ case 0x7: svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; break;
+ case 0x8: svga->clock = (cpuclock * (double)(1ull << 32)) / 88000000.0; break;
+ case 0x9: svga->clock = (cpuclock * (double)(1ull << 32)) / 98000000.0; break;
+ case 0xa: svga->clock = (cpuclock * (double)(1ull << 32)) / 118800000.0; break;
+ case 0xb: svga->clock = (cpuclock * (double)(1ull << 32)) / 108000000.0; break;
+ case 0xc: svga->clock = (cpuclock * (double)(1ull << 32)) / 72000000.0; break;
+ case 0xd: svga->clock = (cpuclock * (double)(1ull << 32)) / 77000000.0; break;
+ case 0xe: svga->clock = (cpuclock * (double)(1ull << 32)) / 80000000.0; break;
+ case 0xf: svga->clock = (cpuclock * (double)(1ull << 32)) / 75000000.0; break;
}
- if (tvga->oldctrl2 & 0x10)
+ if (tvga->id == TVGA_9000)
{
+ /*TVGA9000 doesn't seem to have support for a 'high res' 256 colour mode
+ (without the VGA pixel doubling). Instead it implements these modes by
+ doubling the horizontal pixel count and pixel clock. Hence we use a
+ basic heuristic to detect this*/
+ if (svga->interlace)
+ high_res_256 = (svga->htotal * 8) > (svga->vtotal * 4);
+ else
+ high_res_256 = (svga->htotal * 8) > (svga->vtotal * 2);
+ }
+ if ((tvga->oldctrl2 & 0x10) || high_res_256)
+ {
+ if (high_res_256)
+ svga->hdisp /= 2;
switch (svga->bpp)
{
case 8:
@@ -280,31 +344,46 @@ void tvga_recalctimings(svga_t *svga)
}
}
-void *tvga8900d_init()
+static void *tvga_common_init(char *fn, uint32_t id, int vram_size)
{
tvga_t *tvga = malloc(sizeof(tvga_t));
memset(tvga, 0, sizeof(tvga_t));
-
- tvga->vram_size = device_get_config_int("memory") << 10;
+
+ tvga->vram_size = vram_size << 10;
tvga->vram_mask = tvga->vram_size - 1;
-
- rom_init(&tvga->bios_rom, "trident.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
-
+ tvga->id = id;
+
+ rom_init(&tvga->bios_rom, fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
+
svga_init(&tvga->svga, tvga, tvga->vram_size,
tvga_recalctimings,
tvga_in, tvga_out,
NULL,
NULL);
-
+
io_sethandler(0x03c0, 0x0020, tvga_in, NULL, NULL, tvga_out, NULL, NULL, tvga);
return tvga;
}
+static void *tvga8900d_init()
+{
+ int vram_size = device_get_config_int("memory");
+
+ return tvga_common_init("trident.bin", TVGA_8900D, vram_size);
+}
+static void *tvga9000b_init()
+{
+ return tvga_common_init("tvga9000b/BIOS.BIN", TVGA_9000, 512);
+}
static int tvga8900d_available()
{
return rom_present("trident.bin");
}
+static int tvga9000b_available()
+{
+ return rom_present("tvga9000b/BIOS.BIN");
+}
void tvga_close(void *p)
{
@@ -380,3 +459,15 @@ device_t tvga8900d_device =
tvga_add_status_info,
tvga_config
};
+device_t tvga9000b_device =
+{
+ "Trident TVGA 9000B",
+ 0,
+ tvga9000b_init,
+ tvga_close,
+ tvga9000b_available,
+ tvga_speed_changed,
+ tvga_force_redraw,
+ tvga_add_status_info,
+ NULL
+};
diff --git a/src/vid_tvga.h b/src/vid_tvga.h
index d55ff65..c2c1019 100644
--- a/src/vid_tvga.h
+++ b/src/vid_tvga.h
@@ -1 +1,2 @@
extern device_t tvga8900d_device;
+extern device_t tvga9000b_device;
diff --git a/src/vid_vga.c b/src/vid_vga.c
index 241166f..64bd67c 100644
--- a/src/vid_vga.c
+++ b/src/vid_vga.c
@@ -9,6 +9,8 @@
#include "vid_svga.h"
#include "vid_vga.h"
+svga_t *mb_vga = NULL;
+
typedef struct vga_t
{
svga_t svga;
@@ -84,6 +86,30 @@ uint8_t vga_in(uint16_t addr, void *p)
return temp;
}
+void vga_disable(void *p)
+{
+ vga_t *vga = (vga_t *)p;
+ svga_t *svga = &vga->svga;
+
+// pclog("vga_disable\n");
+ io_removehandler(0x03a0, 0x0040, vga_in, NULL, NULL, vga_out, NULL, NULL, vga);
+ mem_mapping_disable(&svga->mapping);
+}
+
+void vga_enable(void *p)
+{
+ vga_t *vga = (vga_t *)p;
+ svga_t *svga = &vga->svga;
+
+// pclog("vga_enable\n");
+ io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga);
+ if (!(svga->miscout & 1))
+ io_sethandler(0x03a0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga);
+
+ mem_mapping_enable(&svga->mapping);
+}
+
+
void *vga_init()
{
vga_t *vga = malloc(sizeof(vga_t));
@@ -122,6 +148,8 @@ void *ps1vga_init()
vga->svga.bpp = 8;
vga->svga.miscout = 1;
+ mb_vga = &vga->svga;
+
return vga;
}
@@ -134,6 +162,8 @@ void vga_close(void *p)
{
vga_t *vga = (vga_t *)p;
+ mb_vga = NULL;
+
svga_close(&vga->svga);
free(vga);
diff --git a/src/vid_vga.h b/src/vid_vga.h
index 3bf9459..cf58f72 100644
--- a/src/vid_vga.h
+++ b/src/vid_vga.h
@@ -1,2 +1,8 @@
extern device_t vga_device;
extern device_t ps1vga_device;
+
+void vga_disable(void *p);
+void vga_enable(void *p);
+
+struct svga_t;
+extern struct svga_t *mb_vga;
diff --git a/src/vid_voodoo.c b/src/vid_voodoo.c
index 480374e..4164908 100644
--- a/src/vid_voodoo.c
+++ b/src/vid_voodoo.c
@@ -10,1079 +10,33 @@
#include "video.h"
#include "vid_svga.h"
#include "vid_voodoo.h"
+#include "vid_voodoo_common.h"
+#include "vid_voodoo_blitter.h"
+#include "vid_voodoo_display.h"
#include "vid_voodoo_dither.h"
+#include "vid_voodoo_fb.h"
+#include "vid_voodoo_fifo.h"
+#include "vid_voodoo_reg.h"
+#include "vid_voodoo_regs.h"
+#include "vid_voodoo_render.h"
+#include "vid_voodoo_texture.h"
-#ifdef MIN
-#undef MIN
-#endif
-#ifdef CLAMP
-#undef CLAMP
-#endif
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
+rgba8_t rgb332[0x100], ai44[0x100], rgb565[0x10000], argb1555[0x10000], argb4444[0x10000], ai88[0x10000];
-#define CLAMP(x) (((x) < 0) ? 0 : (((x) > 0xff) ? 0xff : (x)))
-#define CLAMP16(x) (((x) < 0) ? 0 : (((x) > 0xffff) ? 0xffff : (x)))
-#define LOD_MAX 8
-
-#define TEX_DIRTY_SHIFT 10
-
-#define TEX_CACHE_MAX 64
-
-enum
-{
- VOODOO_1 = 0,
- VOODOO_SB50 = 1,
- VOODOO_2 = 2
-};
-
-static uint32_t texture_offset[LOD_MAX+3] =
-{
- 0,
- 256*256,
- 256*256 + 128*128,
- 256*256 + 128*128 + 64*64,
- 256*256 + 128*128 + 64*64 + 32*32,
- 256*256 + 128*128 + 64*64 + 32*32 + 16*16,
- 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8,
- 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4,
- 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2,
- 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2 + 1*1,
- 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2 + 1*1 + 1
-};
-
-static int tris = 0;
+int tris = 0;
static uint64_t status_time = 0;
-typedef union int_float
-{
- uint32_t i;
- float f;
-} int_float;
-typedef struct rgb_t
-{
- uint8_t b, g, r;
- uint8_t pad;
-} rgb_t;
-typedef struct rgba8_t
-{
- uint8_t b, g, r, a;
-} rgba8_t;
-
-typedef union rgba_u
-{
- struct
- {
- uint8_t b, g, r, a;
- } rgba;
- uint32_t u;
-} rgba_u;
-
-#define FIFO_SIZE 65536
-#define FIFO_MASK (FIFO_SIZE - 1)
-#define FIFO_ENTRY_SIZE (1 << 31)
-
-#define FIFO_ENTRIES (voodoo->fifo_write_idx - voodoo->fifo_read_idx)
-#define FIFO_FULL ((voodoo->fifo_write_idx - voodoo->fifo_read_idx) >= FIFO_SIZE-4)
-#define FIFO_EMPTY (voodoo->fifo_read_idx == voodoo->fifo_write_idx)
-
-#define FIFO_TYPE 0xff000000
-#define FIFO_ADDR 0x00ffffff
-
-enum
-{
- FIFO_INVALID = (0x00 << 24),
- FIFO_WRITEL_REG = (0x01 << 24),
- FIFO_WRITEW_FB = (0x02 << 24),
- FIFO_WRITEL_FB = (0x03 << 24),
- FIFO_WRITEL_TEX = (0x04 << 24)
-};
-
-#define PARAM_SIZE 1024
-#define PARAM_MASK (PARAM_SIZE - 1)
-#define PARAM_ENTRY_SIZE (1 << 31)
-
-#define PARAM_ENTRIES_1 (voodoo->params_write_idx - voodoo->params_read_idx[0])
-#define PARAM_ENTRIES_2 (voodoo->params_write_idx - voodoo->params_read_idx[1])
-#define PARAM_FULL_1 ((voodoo->params_write_idx - voodoo->params_read_idx[0]) >= PARAM_SIZE)
-#define PARAM_FULL_2 ((voodoo->params_write_idx - voodoo->params_read_idx[1]) >= PARAM_SIZE)
-#define PARAM_EMPTY_1 (voodoo->params_read_idx[0] == voodoo->params_write_idx)
-#define PARAM_EMPTY_2 (voodoo->params_read_idx[1] == voodoo->params_write_idx)
-
-typedef struct
-{
- uint32_t addr_type;
- uint32_t val;
-} fifo_entry_t;
-
-static rgba8_t rgb332[0x100], ai44[0x100], rgb565[0x10000], argb1555[0x10000], argb4444[0x10000], ai88[0x10000];
-
-typedef struct voodoo_params_t
-{
- int command;
-
- int32_t vertexAx, vertexAy, vertexBx, vertexBy, vertexCx, vertexCy;
-
- uint32_t startR, startG, startB, startZ, startA;
-
- int32_t dBdX, dGdX, dRdX, dAdX, dZdX;
-
- int32_t dBdY, dGdY, dRdY, dAdY, dZdY;
-
- int64_t startW, dWdX, dWdY;
-
- struct
- {
- int64_t startS, startT, startW, p1;
- int64_t dSdX, dTdX, dWdX, p2;
- int64_t dSdY, dTdY, dWdY, p3;
- } tmu[2];
-
- uint32_t color0, color1;
-
- uint32_t fbzMode;
- uint32_t fbzColorPath;
-
- uint32_t fogMode;
- rgb_t fogColor;
- struct
- {
- uint8_t fog, dfog;
- } fogTable[64];
-
- uint32_t alphaMode;
-
- uint32_t zaColor;
-
- int chromaKey_r, chromaKey_g, chromaKey_b;
- uint32_t chromaKey;
-
- uint32_t textureMode[2];
- uint32_t tLOD[2];
-
- uint32_t texBaseAddr[2], texBaseAddr1[2], texBaseAddr2[2], texBaseAddr38[2];
-
- uint32_t tex_base[2][LOD_MAX+2];
- uint32_t tex_end[2][LOD_MAX+2];
- int tex_width[2];
- int tex_w_mask[2][LOD_MAX+2];
- int tex_w_nmask[2][LOD_MAX+2];
- int tex_h_mask[2][LOD_MAX+2];
- int tex_shift[2][LOD_MAX+2];
- int tex_lod[2][LOD_MAX+2];
- int tex_entry[2];
- int detail_max[2], detail_bias[2], detail_scale[2];
-
- uint32_t draw_offset, aux_offset;
-
- int tformat[2];
-
- int clipLeft, clipRight, clipLowY, clipHighY;
-
- int sign;
-
- uint32_t front_offset;
-
- uint32_t swapbufferCMD;
-
- uint32_t stipple;
-} voodoo_params_t;
-
-typedef struct texture_t
-{
- uint32_t base;
- uint32_t tLOD;
- volatile int refcount, refcount_r[2];
- int is16;
- uint32_t palette_checksum;
- uint32_t addr_start[4], addr_end[4];
- uint32_t *data;
-} texture_t;
-
-typedef struct vert_t
-{
- float sVx, sVy;
- float sRed, sGreen, sBlue, sAlpha;
- float sVz, sWb;
- float sW0, sS0, sT0;
- float sW1, sS1, sT1;
-} vert_t;
-
-typedef struct voodoo_t
-{
- mem_mapping_t mapping;
-
- int pci_enable;
-
- uint8_t dac_data[8];
- int dac_reg, dac_reg_ff;
- uint8_t dac_readdata;
- uint16_t dac_pll_regs[16];
-
- float pixel_clock;
- uint64_t line_time;
-
- voodoo_params_t params;
-
- uint32_t fbiInit0, fbiInit1, fbiInit2, fbiInit3, fbiInit4;
- uint32_t fbiInit5, fbiInit6, fbiInit7; /*Voodoo 2*/
-
- uint32_t initEnable;
-
- uint32_t lfbMode;
-
- uint32_t memBaseAddr;
-
- int_float fvertexAx, fvertexAy, fvertexBx, fvertexBy, fvertexCx, fvertexCy;
-
- uint32_t front_offset, back_offset;
-
- uint32_t fb_read_offset, fb_write_offset;
-
- int row_width;
- int block_width;
-
- uint8_t *fb_mem, *tex_mem[2];
- uint16_t *tex_mem_w[2];
-
- int rgb_sel;
-
- uint32_t trexInit1[2];
-
- uint32_t tmuConfig;
-
- int swap_count;
-
- int disp_buffer, draw_buffer;
- pc_timer_t timer;
-
- int line;
- svga_t *svga;
-
- uint32_t backPorch;
- uint32_t videoDimensions;
- uint32_t hSync, vSync;
-
- int h_total, v_total, v_disp;
- int h_disp;
- int v_retrace;
-
- struct
- {
- uint32_t y[4], i[4], q[4];
- } nccTable[2][2];
-
- rgba_u palette[2][256];
-
- rgba_u ncc_lookup[2][2][256];
- int ncc_dirty[2];
-
- thread_t *fifo_thread;
- thread_t *render_thread[2];
- event_t *wake_fifo_thread;
- event_t *wake_main_thread;
- event_t *fifo_not_full_event;
- event_t *render_not_full_event[2];
- event_t *wake_render_thread[2];
-
- int voodoo_busy;
- int render_voodoo_busy[2];
-
- int render_threads;
- int odd_even_mask;
-
- int pixel_count[2], texel_count[2], tri_count, frame_count;
- int pixel_count_old[2], texel_count_old[2];
- int wr_count, rd_count, tex_count;
-
- int retrace_count;
- int swap_interval;
- uint32_t swap_offset;
- int swap_pending;
-
- int bilinear_enabled;
-
- int fb_size;
- uint32_t fb_mask;
-
- int texture_size;
- uint32_t texture_mask;
-
- int dual_tmus;
- int type;
-
- fifo_entry_t fifo[FIFO_SIZE];
- volatile int fifo_read_idx, fifo_write_idx;
- volatile int cmd_read, cmd_written, cmd_written_fifo;
-
- voodoo_params_t params_buffer[PARAM_SIZE];
- volatile int params_read_idx[2], params_write_idx;
-
- uint32_t cmdfifo_base, cmdfifo_end;
- int cmdfifo_rp;
- volatile int cmdfifo_depth_rd, cmdfifo_depth_wr;
- uint32_t cmdfifo_amin, cmdfifo_amax;
-
- uint32_t sSetupMode;
- vert_t verts[4];
- int vertex_num;
- int num_verticies;
-
- int flush;
-
- int scrfilter;
- int scrfilterEnabled;
- int scrfilterThreshold;
- int scrfilterThresholdOld;
-
- uint32_t last_write_addr;
-
- uint32_t fbiPixelsIn;
- uint32_t fbiChromaFail;
- uint32_t fbiZFuncFail;
- uint32_t fbiAFuncFail;
- uint32_t fbiPixelsOut;
-
- uint32_t bltSrcBaseAddr;
- uint32_t bltDstBaseAddr;
- int bltSrcXYStride, bltDstXYStride;
- uint32_t bltSrcChromaRange, bltDstChromaRange;
- int bltSrcChromaMinR, bltSrcChromaMinG, bltSrcChromaMinB;
- int bltSrcChromaMaxR, bltSrcChromaMaxG, bltSrcChromaMaxB;
- int bltDstChromaMinR, bltDstChromaMinG, bltDstChromaMinB;
- int bltDstChromaMaxR, bltDstChromaMaxG, bltDstChromaMaxB;
-
- int bltClipRight, bltClipLeft;
- int bltClipHighY, bltClipLowY;
-
- int bltSrcX, bltSrcY;
- int bltDstX, bltDstY;
- int bltSizeX, bltSizeY;
- int bltRop[4];
- uint16_t bltColorFg, bltColorBg;
-
- uint32_t bltCommand;
-
- struct
- {
- int dst_x, dst_y;
- int cur_x;
- int size_x, size_y;
- int x_dir, y_dir;
- int dst_stride;
- } blt;
-
- rgb_t clutData[33];
- int clutData_dirty;
- rgb_t clutData256[256];
- uint32_t video_16to32[0x10000];
-
- uint8_t dirty_line[1024];
- int dirty_line_low, dirty_line_high;
-
- int fb_write_buffer, fb_draw_buffer;
- int buffer_cutoff;
-
- int read_time, write_time, burst_time;
-
- pc_timer_t wake_timer;
-
- uint8_t thefilter[256][256]; // pixel filter, feeding from one or two
- uint8_t thefilterg[256][256]; // for green
- uint8_t thefilterb[256][256]; // for blue
-
- /* the voodoo adds purple lines for some reason */
- uint16_t purpleline[256][3];
-
- texture_t texture_cache[2][TEX_CACHE_MAX];
- uint8_t texture_present[2][4096];
- int texture_last_removed;
-
- uint32_t palette_checksum[2];
- int palette_dirty[2];
-
- uint64_t time;
- int render_time[2];
-
- int use_recompiler;
- void *codegen_data;
-
- struct voodoo_set_t *set;
-} voodoo_t;
-
-typedef struct voodoo_set_t
-{
- voodoo_t *voodoos[2];
-
- mem_mapping_t snoop_mapping;
-
- int nr_cards;
-} voodoo_set_t;
-
-static inline void wait_for_render_thread_idle(voodoo_t *voodoo);
-
-enum
-{
- SST_status = 0x000,
- SST_intrCtrl = 0x004,
-
- SST_vertexAx = 0x008,
- SST_vertexAy = 0x00c,
- SST_vertexBx = 0x010,
- SST_vertexBy = 0x014,
- SST_vertexCx = 0x018,
- SST_vertexCy = 0x01c,
-
- SST_startR = 0x0020,
- SST_startG = 0x0024,
- SST_startB = 0x0028,
- SST_startZ = 0x002c,
- SST_startA = 0x0030,
- SST_startS = 0x0034,
- SST_startT = 0x0038,
- SST_startW = 0x003c,
-
- SST_dRdX = 0x0040,
- SST_dGdX = 0x0044,
- SST_dBdX = 0x0048,
- SST_dZdX = 0x004c,
- SST_dAdX = 0x0050,
- SST_dSdX = 0x0054,
- SST_dTdX = 0x0058,
- SST_dWdX = 0x005c,
-
- SST_dRdY = 0x0060,
- SST_dGdY = 0x0064,
- SST_dBdY = 0x0068,
- SST_dZdY = 0x006c,
- SST_dAdY = 0x0070,
- SST_dSdY = 0x0074,
- SST_dTdY = 0x0078,
- SST_dWdY = 0x007c,
-
- SST_triangleCMD = 0x0080,
-
- SST_fvertexAx = 0x088,
- SST_fvertexAy = 0x08c,
- SST_fvertexBx = 0x090,
- SST_fvertexBy = 0x094,
- SST_fvertexCx = 0x098,
- SST_fvertexCy = 0x09c,
-
- SST_fstartR = 0x00a0,
- SST_fstartG = 0x00a4,
- SST_fstartB = 0x00a8,
- SST_fstartZ = 0x00ac,
- SST_fstartA = 0x00b0,
- SST_fstartS = 0x00b4,
- SST_fstartT = 0x00b8,
- SST_fstartW = 0x00bc,
-
- SST_fdRdX = 0x00c0,
- SST_fdGdX = 0x00c4,
- SST_fdBdX = 0x00c8,
- SST_fdZdX = 0x00cc,
- SST_fdAdX = 0x00d0,
- SST_fdSdX = 0x00d4,
- SST_fdTdX = 0x00d8,
- SST_fdWdX = 0x00dc,
-
- SST_fdRdY = 0x00e0,
- SST_fdGdY = 0x00e4,
- SST_fdBdY = 0x00e8,
- SST_fdZdY = 0x00ec,
- SST_fdAdY = 0x00f0,
- SST_fdSdY = 0x00f4,
- SST_fdTdY = 0x00f8,
- SST_fdWdY = 0x00fc,
-
- SST_ftriangleCMD = 0x0100,
-
- SST_fbzColorPath = 0x104,
- SST_fogMode = 0x108,
-
- SST_alphaMode = 0x10c,
- SST_fbzMode = 0x110,
- SST_lfbMode = 0x114,
-
- SST_clipLeftRight = 0x118,
- SST_clipLowYHighY = 0x11c,
-
- SST_nopCMD = 0x120,
- SST_fastfillCMD = 0x124,
- SST_swapbufferCMD = 0x128,
-
- SST_fogColor = 0x12c,
- SST_zaColor = 0x130,
- SST_chromaKey = 0x134,
-
- SST_userIntrCMD = 0x13c,
- SST_stipple = 0x140,
- SST_color0 = 0x144,
- SST_color1 = 0x148,
-
- SST_fbiPixelsIn = 0x14c,
- SST_fbiChromaFail = 0x150,
- SST_fbiZFuncFail = 0x154,
- SST_fbiAFuncFail = 0x158,
- SST_fbiPixelsOut = 0x15c,
-
- SST_fogTable00 = 0x160,
- SST_fogTable01 = 0x164,
- SST_fogTable02 = 0x168,
- SST_fogTable03 = 0x16c,
- SST_fogTable04 = 0x170,
- SST_fogTable05 = 0x174,
- SST_fogTable06 = 0x178,
- SST_fogTable07 = 0x17c,
- SST_fogTable08 = 0x180,
- SST_fogTable09 = 0x184,
- SST_fogTable0a = 0x188,
- SST_fogTable0b = 0x18c,
- SST_fogTable0c = 0x190,
- SST_fogTable0d = 0x194,
- SST_fogTable0e = 0x198,
- SST_fogTable0f = 0x19c,
- SST_fogTable10 = 0x1a0,
- SST_fogTable11 = 0x1a4,
- SST_fogTable12 = 0x1a8,
- SST_fogTable13 = 0x1ac,
- SST_fogTable14 = 0x1b0,
- SST_fogTable15 = 0x1b4,
- SST_fogTable16 = 0x1b8,
- SST_fogTable17 = 0x1bc,
- SST_fogTable18 = 0x1c0,
- SST_fogTable19 = 0x1c4,
- SST_fogTable1a = 0x1c8,
- SST_fogTable1b = 0x1cc,
- SST_fogTable1c = 0x1d0,
- SST_fogTable1d = 0x1d4,
- SST_fogTable1e = 0x1d8,
- SST_fogTable1f = 0x1dc,
-
- SST_cmdFifoBaseAddr = 0x1e0,
- SST_cmdFifoBump = 0x1e4,
- SST_cmdFifoRdPtr = 0x1e8,
- SST_cmdFifoAMin = 0x1ec,
- SST_cmdFifoAMax = 0x1f0,
- SST_cmdFifoDepth = 0x1f4,
- SST_cmdFifoHoles = 0x1f8,
-
- SST_fbiInit4 = 0x200,
- SST_vRetrace = 0x204,
- SST_backPorch = 0x208,
- SST_videoDimensions = 0x20c,
- SST_fbiInit0 = 0x210,
- SST_fbiInit1 = 0x214,
- SST_fbiInit2 = 0x218,
- SST_fbiInit3 = 0x21c,
- SST_hSync = 0x220,
- SST_vSync = 0x224,
- SST_clutData = 0x228,
- SST_dacData = 0x22c,
-
- SST_scrFilter = 0x230,
-
- SST_hvRetrace = 0x240,
- SST_fbiInit5 = 0x244,
- SST_fbiInit6 = 0x248,
- SST_fbiInit7 = 0x24c,
-
- SST_sSetupMode = 0x260,
- SST_sVx = 0x264,
- SST_sVy = 0x268,
- SST_sARGB = 0x26c,
- SST_sRed = 0x270,
- SST_sGreen = 0x274,
- SST_sBlue = 0x278,
- SST_sAlpha = 0x27c,
- SST_sVz = 0x280,
- SST_sWb = 0x284,
- SST_sW0 = 0x288,
- SST_sS0 = 0x28c,
- SST_sT0 = 0x290,
- SST_sW1 = 0x294,
- SST_sS1 = 0x298,
- SST_sT1 = 0x29c,
-
- SST_sDrawTriCMD = 0x2a0,
- SST_sBeginTriCMD = 0x2a4,
-
- SST_bltSrcBaseAddr = 0x2c0,
- SST_bltDstBaseAddr = 0x2c4,
- SST_bltXYStrides = 0x2c8,
- SST_bltSrcChromaRange = 0x2cc,
- SST_bltDstChromaRange = 0x2d0,
- SST_bltClipX = 0x2d4,
- SST_bltClipY = 0x2d8,
-
- SST_bltSrcXY = 0x2e0,
- SST_bltDstXY = 0x2e4,
- SST_bltSize = 0x2e8,
- SST_bltRop = 0x2ec,
- SST_bltColor = 0x2f0,
-
- SST_bltCommand = 0x2f8,
- SST_bltData = 0x2fc,
-
- SST_textureMode = 0x300,
- SST_tLOD = 0x304,
- SST_tDetail = 0x308,
- SST_texBaseAddr = 0x30c,
- SST_texBaseAddr1 = 0x310,
- SST_texBaseAddr2 = 0x314,
- SST_texBaseAddr38 = 0x318,
-
- SST_trexInit1 = 0x320,
-
- SST_nccTable0_Y0 = 0x324,
- SST_nccTable0_Y1 = 0x328,
- SST_nccTable0_Y2 = 0x32c,
- SST_nccTable0_Y3 = 0x330,
- SST_nccTable0_I0 = 0x334,
- SST_nccTable0_I1 = 0x338,
- SST_nccTable0_I2 = 0x33c,
- SST_nccTable0_I3 = 0x340,
- SST_nccTable0_Q0 = 0x344,
- SST_nccTable0_Q1 = 0x348,
- SST_nccTable0_Q2 = 0x34c,
- SST_nccTable0_Q3 = 0x350,
-
- SST_nccTable1_Y0 = 0x354,
- SST_nccTable1_Y1 = 0x358,
- SST_nccTable1_Y2 = 0x35c,
- SST_nccTable1_Y3 = 0x360,
- SST_nccTable1_I0 = 0x364,
- SST_nccTable1_I1 = 0x368,
- SST_nccTable1_I2 = 0x36c,
- SST_nccTable1_I3 = 0x370,
- SST_nccTable1_Q0 = 0x374,
- SST_nccTable1_Q1 = 0x378,
- SST_nccTable1_Q2 = 0x37c,
- SST_nccTable1_Q3 = 0x380,
-
- SST_remap_status = 0x000 | 0x400,
-
- SST_remap_vertexAx = 0x008 | 0x400,
- SST_remap_vertexAy = 0x00c | 0x400,
- SST_remap_vertexBx = 0x010 | 0x400,
- SST_remap_vertexBy = 0x014 | 0x400,
- SST_remap_vertexCx = 0x018 | 0x400,
- SST_remap_vertexCy = 0x01c | 0x400,
-
- SST_remap_startR = 0x0020 | 0x400,
- SST_remap_startG = 0x002c | 0x400,
- SST_remap_startB = 0x0038 | 0x400,
- SST_remap_startZ = 0x0044 | 0x400,
- SST_remap_startA = 0x0050 | 0x400,
- SST_remap_startS = 0x005c | 0x400,
- SST_remap_startT = 0x0068 | 0x400,
- SST_remap_startW = 0x0074 | 0x400,
-
- SST_remap_dRdX = 0x0024 | 0x400,
- SST_remap_dGdX = 0x0030 | 0x400,
- SST_remap_dBdX = 0x003c | 0x400,
- SST_remap_dZdX = 0x0048 | 0x400,
- SST_remap_dAdX = 0x0054 | 0x400,
- SST_remap_dSdX = 0x0060 | 0x400,
- SST_remap_dTdX = 0x006c | 0x400,
- SST_remap_dWdX = 0x0078 | 0x400,
-
- SST_remap_dRdY = 0x0028 | 0x400,
- SST_remap_dGdY = 0x0034 | 0x400,
- SST_remap_dBdY = 0x0040 | 0x400,
- SST_remap_dZdY = 0x004c | 0x400,
- SST_remap_dAdY = 0x0058 | 0x400,
- SST_remap_dSdY = 0x0064 | 0x400,
- SST_remap_dTdY = 0x0070 | 0x400,
- SST_remap_dWdY = 0x007c | 0x400,
-
- SST_remap_triangleCMD = 0x0080 | 0x400,
-
- SST_remap_fvertexAx = 0x088 | 0x400,
- SST_remap_fvertexAy = 0x08c | 0x400,
- SST_remap_fvertexBx = 0x090 | 0x400,
- SST_remap_fvertexBy = 0x094 | 0x400,
- SST_remap_fvertexCx = 0x098 | 0x400,
- SST_remap_fvertexCy = 0x09c | 0x400,
-
- SST_remap_fstartR = 0x00a0 | 0x400,
- SST_remap_fstartG = 0x00ac | 0x400,
- SST_remap_fstartB = 0x00b8 | 0x400,
- SST_remap_fstartZ = 0x00c4 | 0x400,
- SST_remap_fstartA = 0x00d0 | 0x400,
- SST_remap_fstartS = 0x00dc | 0x400,
- SST_remap_fstartT = 0x00e8 | 0x400,
- SST_remap_fstartW = 0x00f4 | 0x400,
-
- SST_remap_fdRdX = 0x00a4 | 0x400,
- SST_remap_fdGdX = 0x00b0 | 0x400,
- SST_remap_fdBdX = 0x00bc | 0x400,
- SST_remap_fdZdX = 0x00c8 | 0x400,
- SST_remap_fdAdX = 0x00d4 | 0x400,
- SST_remap_fdSdX = 0x00e0 | 0x400,
- SST_remap_fdTdX = 0x00ec | 0x400,
- SST_remap_fdWdX = 0x00f8 | 0x400,
-
- SST_remap_fdRdY = 0x00a8 | 0x400,
- SST_remap_fdGdY = 0x00b4 | 0x400,
- SST_remap_fdBdY = 0x00c0 | 0x400,
- SST_remap_fdZdY = 0x00cc | 0x400,
- SST_remap_fdAdY = 0x00d8 | 0x400,
- SST_remap_fdSdY = 0x00e4 | 0x400,
- SST_remap_fdTdY = 0x00f0 | 0x400,
- SST_remap_fdWdY = 0x00fc | 0x400,
-};
-
-enum
-{
- LFB_WRITE_FRONT = 0x0000,
- LFB_WRITE_BACK = 0x0010,
- LFB_WRITE_MASK = 0x0030
-};
-
-enum
-{
- LFB_READ_FRONT = 0x0000,
- LFB_READ_BACK = 0x0040,
- LFB_READ_AUX = 0x0080,
- LFB_READ_MASK = 0x00c0
-};
-
-enum
-{
- LFB_FORMAT_RGB565 = 0,
- LFB_FORMAT_RGB555 = 1,
- LFB_FORMAT_ARGB1555 = 2,
- LFB_FORMAT_ARGB8888 = 5,
- LFB_FORMAT_DEPTH = 15,
- LFB_FORMAT_MASK = 15
-};
-
-enum
-{
- LFB_WRITE_COLOUR = 1,
- LFB_WRITE_DEPTH = 2
-};
-
-enum
-{
- FBZ_CHROMAKEY = (1 << 1),
- FBZ_W_BUFFER = (1 << 3),
- FBZ_DEPTH_ENABLE = (1 << 4),
-
- FBZ_DITHER = (1 << 8),
- FBZ_RGB_WMASK = (1 << 9),
- FBZ_DEPTH_WMASK = (1 << 10),
- FBZ_DITHER_2x2 = (1 << 11),
-
- FBZ_DRAW_FRONT = 0x0000,
- FBZ_DRAW_BACK = 0x4000,
- FBZ_DRAW_MASK = 0xc000,
-
- FBZ_DEPTH_BIAS = (1 << 16),
-
- FBZ_DEPTH_SOURCE = (1 << 20),
-
- FBZ_PARAM_ADJUST = (1 << 26)
-};
-
-enum
-{
- TEX_RGB332 = 0x0,
- TEX_Y4I2Q2 = 0x1,
- TEX_A8 = 0x2,
- TEX_I8 = 0x3,
- TEX_AI8 = 0x4,
- TEX_PAL8 = 0x5,
- TEX_APAL8 = 0x6,
- TEX_ARGB8332 = 0x8,
- TEX_A8Y4I2Q2 = 0x9,
- TEX_R5G6B5 = 0xa,
- TEX_ARGB1555 = 0xb,
- TEX_ARGB4444 = 0xc,
- TEX_A8I8 = 0xd,
- TEX_APAL88 = 0xe
-};
-
-enum
-{
- TEXTUREMODE_NCC_SEL = (1 << 5),
- TEXTUREMODE_TCLAMPS = (1 << 6),
- TEXTUREMODE_TCLAMPT = (1 << 7),
- TEXTUREMODE_TRILINEAR = (1 << 30)
-};
-
-enum
-{
- FBIINIT0_VGA_PASS = 1,
- FBIINIT0_GRAPHICS_RESET = (1 << 1)
-};
-
-enum
-{
- FBIINIT1_MULTI_SST = (1 << 2), /*Voodoo Graphics only*/
- FBIINIT1_VIDEO_RESET = (1 << 8),
- FBIINIT1_SLI_ENABLE = (1 << 23)
-};
-
-enum
-{
- FBIINIT2_SWAP_ALGORITHM_MASK = (3 << 9)
-};
-
-enum
-{
- FBIINIT2_SWAP_ALGORITHM_DAC_VSYNC = (0 << 9),
- FBIINIT2_SWAP_ALGORITHM_DAC_DATA = (1 << 9),
- FBIINIT2_SWAP_ALGORITHM_PCI_FIFO_STALL = (2 << 9),
- FBIINIT2_SWAP_ALGORITHM_SLI_SYNC = (3 << 9)
-};
-
-enum
-{
- FBIINIT3_REMAP = 1
-};
-
-enum
-{
- FBIINIT5_MULTI_CVG = (1 << 14)
-};
-
-enum
-{
- FBIINIT7_CMDFIFO_ENABLE = (1 << 8)
-};
-
-enum
-{
- CC_LOCALSELECT_ITER_RGB = 0,
- CC_LOCALSELECT_TEX = 1,
- CC_LOCALSELECT_COLOR1 = 2,
- CC_LOCALSELECT_LFB = 3
-};
-
-enum
-{
- CCA_LOCALSELECT_ITER_A = 0,
- CCA_LOCALSELECT_COLOR0 = 1,
- CCA_LOCALSELECT_ITER_Z = 2
-};
-
-enum
-{
- C_SEL_ITER_RGB = 0,
- C_SEL_TEX = 1,
- C_SEL_COLOR1 = 2,
- C_SEL_LFB = 3
-};
-
-enum
-{
- A_SEL_ITER_A = 0,
- A_SEL_TEX = 1,
- A_SEL_COLOR1 = 2,
- A_SEL_LFB = 3
-};
-
-enum
-{
- CC_MSELECT_ZERO = 0,
- CC_MSELECT_CLOCAL = 1,
- CC_MSELECT_AOTHER = 2,
- CC_MSELECT_ALOCAL = 3,
- CC_MSELECT_TEX = 4,
- CC_MSELECT_TEXRGB = 5
-};
-
-enum
-{
- CCA_MSELECT_ZERO = 0,
- CCA_MSELECT_ALOCAL = 1,
- CCA_MSELECT_AOTHER = 2,
- CCA_MSELECT_ALOCAL2 = 3,
- CCA_MSELECT_TEX = 4
-};
-
-enum
-{
- TC_MSELECT_ZERO = 0,
- TC_MSELECT_CLOCAL = 1,
- TC_MSELECT_AOTHER = 2,
- TC_MSELECT_ALOCAL = 3,
- TC_MSELECT_DETAIL = 4,
- TC_MSELECT_LOD_FRAC = 5
-};
-
-enum
-{
- TCA_MSELECT_ZERO = 0,
- TCA_MSELECT_CLOCAL = 1,
- TCA_MSELECT_AOTHER = 2,
- TCA_MSELECT_ALOCAL = 3,
- TCA_MSELECT_DETAIL = 4,
- TCA_MSELECT_LOD_FRAC = 5
-};
-
-enum
-{
- CC_ADD_CLOCAL = 1,
- CC_ADD_ALOCAL = 2
-};
-
-enum
-{
- CCA_ADD_CLOCAL = 1,
- CCA_ADD_ALOCAL = 2
-};
-
-enum
-{
- AFUNC_AZERO = 0x0,
- AFUNC_ASRC_ALPHA = 0x1,
- AFUNC_A_COLOR = 0x2,
- AFUNC_ADST_ALPHA = 0x3,
- AFUNC_AONE = 0x4,
- AFUNC_AOMSRC_ALPHA = 0x5,
- AFUNC_AOM_COLOR = 0x6,
- AFUNC_AOMDST_ALPHA = 0x7,
- AFUNC_ASATURATE = 0xf
-};
-
-enum
-{
- AFUNC_ACOLORBEFOREFOG = 0xf
-};
-
-enum
-{
- AFUNC_NEVER = 0,
- AFUNC_LESSTHAN = 1,
- AFUNC_EQUAL = 2,
- AFUNC_LESSTHANEQUAL = 3,
- AFUNC_GREATERTHAN = 4,
- AFUNC_NOTEQUAL = 5,
- AFUNC_GREATERTHANEQUAL = 6,
- AFUNC_ALWAYS = 7
-};
-
-enum
-{
- DEPTHOP_NEVER = 0,
- DEPTHOP_LESSTHAN = 1,
- DEPTHOP_EQUAL = 2,
- DEPTHOP_LESSTHANEQUAL = 3,
- DEPTHOP_GREATERTHAN = 4,
- DEPTHOP_NOTEQUAL = 5,
- DEPTHOP_GREATERTHANEQUAL = 6,
- DEPTHOP_ALWAYS = 7
-};
-
-enum
-{
- FOG_ENABLE = 0x01,
- FOG_ADD = 0x02,
- FOG_MULT = 0x04,
- FOG_ALPHA = 0x08,
- FOG_Z = 0x10,
- FOG_W = 0x18,
- FOG_CONSTANT = 0x20
-};
-
-enum
-{
- LOD_ODD = (1 << 18),
- LOD_SPLIT = (1 << 19),
- LOD_S_IS_WIDER = (1 << 20),
- LOD_TMULTIBASEADDR = (1 << 24),
- LOD_TMIRROR_S = (1 << 28),
- LOD_TMIRROR_T = (1 << 29)
-};
-enum
-{
- CMD_INVALID = 0,
- CMD_DRAWTRIANGLE,
- CMD_FASTFILL,
- CMD_SWAPBUF
-};
-
-enum
-{
- FBZCP_TEXTURE_ENABLED = (1 << 27)
-};
-
-enum
-{
- BLTCMD_SRC_TILED = (1 << 14),
- BLTCMD_DST_TILED = (1 << 15)
-};
-
-enum
-{
- INITENABLE_SLI_MASTER_SLAVE = (1 << 11)
-};
-
-#define TEXTUREMODE_MASK 0x3ffff000
-#define TEXTUREMODE_PASSTHROUGH 0
-
-#define TEXTUREMODE_LOCAL_MASK 0x00643000
-#define TEXTUREMODE_LOCAL 0x00241000
-
-static void voodoo_threshold_check(voodoo_t *voodoo);
-
-static void voodoo_update_ncc(voodoo_t *voodoo, int tmu)
-{
- int tbl;
-
- for (tbl = 0; tbl < 2; tbl++)
- {
- int col;
-
- for (col = 0; col < 256; col++)
- {
- int y = (col >> 4), i = (col >> 2) & 3, q = col & 3;
- int i_r, i_g, i_b;
- int q_r, q_g, q_b;
-
- y = (voodoo->nccTable[tmu][tbl].y[y >> 2] >> ((y & 3) * 8)) & 0xff;
-
- i_r = (voodoo->nccTable[tmu][tbl].i[i] >> 18) & 0x1ff;
- if (i_r & 0x100)
- i_r |= 0xfffffe00;
- i_g = (voodoo->nccTable[tmu][tbl].i[i] >> 9) & 0x1ff;
- if (i_g & 0x100)
- i_g |= 0xfffffe00;
- i_b = voodoo->nccTable[tmu][tbl].i[i] & 0x1ff;
- if (i_b & 0x100)
- i_b |= 0xfffffe00;
-
- q_r = (voodoo->nccTable[tmu][tbl].q[q] >> 18) & 0x1ff;
- if (q_r & 0x100)
- q_r |= 0xfffffe00;
- q_g = (voodoo->nccTable[tmu][tbl].q[q] >> 9) & 0x1ff;
- if (q_g & 0x100)
- q_g |= 0xfffffe00;
- q_b = voodoo->nccTable[tmu][tbl].q[q] & 0x1ff;
- if (q_b & 0x100)
- q_b |= 0xfffffe00;
-
- voodoo->ncc_lookup[tmu][tbl][col].rgba.r = CLAMP(y + i_r + q_r);
- voodoo->ncc_lookup[tmu][tbl][col].rgba.g = CLAMP(y + i_g + q_g);
- voodoo->ncc_lookup[tmu][tbl][col].rgba.b = CLAMP(y + i_b + q_b);
- voodoo->ncc_lookup[tmu][tbl][col].rgba.a = 0xff;
- }
- }
-}
-
-#define SLI_ENABLED (voodoo->fbiInit1 & FBIINIT1_SLI_ENABLE)
-#define TRIPLE_BUFFER ((voodoo->fbiInit2 & 0x10) || (voodoo->fbiInit5 & 0x600) == 0x400)
-static void voodoo_recalc(voodoo_t *voodoo)
+void voodoo_recalc(voodoo_t *voodoo)
{
uint32_t buffer_offset = ((voodoo->fbiInit2 >> 11) & 511) * 4096;
-
+
+ if (voodoo->type >= VOODOO_BANSHEE)
+ return;
+
voodoo->params.front_offset = voodoo->disp_buffer*buffer_offset;
voodoo->back_offset = voodoo->draw_buffer*buffer_offset;
@@ -1124,7 +78,7 @@ static void voodoo_recalc(voodoo_t *voodoo)
default:
fatal("voodoo_recalc : unknown lfb source\n");
}
-
+
switch (voodoo->params.fbzMode & FBZ_DRAW_MASK)
{
case FBZ_DRAW_FRONT:
@@ -1139,4781 +93,21 @@ static void voodoo_recalc(voodoo_t *voodoo)
default:
fatal("voodoo_recalc : unknown draw buffer\n");
}
-
+
voodoo->block_width = ((voodoo->fbiInit1 >> 4) & 15) * 2;
if (voodoo->fbiInit6 & (1 << 30))
voodoo->block_width += 1;
if (voodoo->fbiInit1 & (1 << 24))
voodoo->block_width += 32;
voodoo->row_width = voodoo->block_width * 32 * 2;
+ voodoo->params.row_width = voodoo->row_width;
+ voodoo->aux_row_width = voodoo->row_width;
+ voodoo->params.aux_row_width = voodoo->aux_row_width;
/* pclog("voodoo_recalc : front_offset %08X back_offset %08X aux_offset %08X draw_offset %08x\n", voodoo->params.front_offset, voodoo->back_offset, voodoo->params.aux_offset, voodoo->params.draw_offset);
pclog(" fb_read_offset %08X fb_write_offset %08X row_width %i %08x %08x\n", voodoo->fb_read_offset, voodoo->fb_write_offset, voodoo->row_width, voodoo->lfbMode, voodoo->params.fbzMode);*/
}
-static void voodoo_recalc_tex(voodoo_t *voodoo, int tmu)
-{
- int aspect = (voodoo->params.tLOD[tmu] >> 21) & 3;
- int width = 256, height = 256;
- int shift = 8;
- int lod;
- uint32_t base = voodoo->params.texBaseAddr[tmu];
- uint32_t offset = 0;
- int tex_lod = 0;
-
- if (voodoo->params.tLOD[tmu] & LOD_S_IS_WIDER)
- height >>= aspect;
- else
- {
- width >>= aspect;
- shift -= aspect;
- }
-
- if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD))
- {
- width >>= 1;
- height >>= 1;
- shift--;
- tex_lod++;
- if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)
- base = voodoo->params.texBaseAddr1[tmu];
- }
-
- for (lod = 0; lod <= LOD_MAX+1; lod++)
- {
- if (!width)
- width = 1;
- if (!height)
- height = 1;
- if (shift < 0)
- shift = 0;
- voodoo->params.tex_base[tmu][lod] = base + offset;
- if (voodoo->params.tformat[tmu] & 8)
- voodoo->params.tex_end[tmu][lod] = base + offset + (width * height * 2);
- else
- voodoo->params.tex_end[tmu][lod] = base + offset + (width * height);
- voodoo->params.tex_w_mask[tmu][lod] = width - 1;
- voodoo->params.tex_w_nmask[tmu][lod] = ~(width - 1);
- voodoo->params.tex_h_mask[tmu][lod] = height - 1;
- voodoo->params.tex_shift[tmu][lod] = shift;
- voodoo->params.tex_lod[tmu][lod] = tex_lod;
-
- if (!(voodoo->params.tLOD[tmu] & LOD_SPLIT) || ((lod & 1) && (voodoo->params.tLOD[tmu] & LOD_ODD)) || (!(lod & 1) && !(voodoo->params.tLOD[tmu] & LOD_ODD)))
- {
- if (!(voodoo->params.tLOD[tmu] & LOD_ODD) || lod != 0)
- {
- if (voodoo->params.tformat[tmu] & 8)
- offset += width * height * 2;
- else
- offset += width * height;
-
- if (voodoo->params.tLOD[tmu] & LOD_SPLIT)
- {
- width >>= 2;
- height >>= 2;
- shift -= 2;
- tex_lod += 2;
- }
- else
- {
- width >>= 1;
- height >>= 1;
- shift--;
- tex_lod++;
- }
-
- if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)
- {
- switch (tex_lod)
- {
- case 0:
- base = voodoo->params.texBaseAddr[tmu];
- break;
- case 1:
- base = voodoo->params.texBaseAddr1[tmu];
- break;
- case 2:
- base = voodoo->params.texBaseAddr2[tmu];
- break;
- default:
- base = voodoo->params.texBaseAddr38[tmu];
- break;
- }
- }
- }
- }
- }
-
- voodoo->params.tex_width[tmu] = width;
-}
-
-#define makergba(r, g, b, a) ((b) | ((g) << 8) | ((r) << 16) | ((a) << 24))
-
-static void use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu)
-{
- int c, d;
- int lod;
- int lod_min, lod_max;
- uint32_t addr = 0, addr_end;
- uint32_t palette_checksum;
-
- lod_min = (params->tLOD[tmu] >> 2) & 15;
- lod_max = (params->tLOD[tmu] >> 8) & 15;
-
- if (params->tformat[tmu] == TEX_PAL8 || params->tformat[tmu] == TEX_APAL8 || params->tformat[tmu] == TEX_APAL88)
- {
- if (voodoo->palette_dirty[tmu])
- {
- palette_checksum = 0;
-
- for (c = 0; c < 256; c++)
- palette_checksum ^= voodoo->palette[tmu][c].u;
-
- voodoo->palette_checksum[tmu] = palette_checksum;
- voodoo->palette_dirty[tmu] = 0;
- }
- else
- palette_checksum = voodoo->palette_checksum[tmu];
- }
- else
- palette_checksum = 0;
-
- if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR))
- addr = params->texBaseAddr1[tmu];
- else
- addr = params->texBaseAddr[tmu];
-
- /*Try to find texture in cache*/
- for (c = 0; c < TEX_CACHE_MAX; c++)
- {
- if (voodoo->texture_cache[tmu][c].base == addr &&
- voodoo->texture_cache[tmu][c].tLOD == (params->tLOD[tmu] & 0xf00fff) &&
- voodoo->texture_cache[tmu][c].palette_checksum == palette_checksum)
- {
- params->tex_entry[tmu] = c;
- voodoo->texture_cache[tmu][c].refcount++;
- return;
- }
- }
-
- /*Texture not found, search for unused texture*/
- do
- {
- for (c = 0; c < TEX_CACHE_MAX; c++)
- {
- voodoo->texture_last_removed++;
- voodoo->texture_last_removed &= (TEX_CACHE_MAX-1);
- if (voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount == voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount_r[0] &&
- (voodoo->render_threads == 1 || voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount == voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount_r[1]))
- break;
- }
- if (c == TEX_CACHE_MAX)
- wait_for_render_thread_idle(voodoo);
- } while (c == TEX_CACHE_MAX);
- if (c == TEX_CACHE_MAX)
- fatal("Texture cache full!\n");
-
- c = voodoo->texture_last_removed;
-
-
- if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR))
- voodoo->texture_cache[tmu][c].base = params->texBaseAddr1[tmu];
- else
- voodoo->texture_cache[tmu][c].base = params->texBaseAddr[tmu];
- voodoo->texture_cache[tmu][c].tLOD = params->tLOD[tmu] & 0xf00fff;
-
- lod_min = (params->tLOD[tmu] >> 2) & 15;
- lod_max = (params->tLOD[tmu] >> 8) & 15;
-// pclog(" add new texture to %i tformat=%i %08x LOD=%i-%i tmu=%i\n", c, voodoo->params.tformat[tmu], params->texBaseAddr[tmu], lod_min, lod_max, tmu);
- lod_min = MIN(lod_min, 8);
- lod_max = MIN(lod_max, 8);
- for (lod = lod_min; lod <= lod_max; lod++)
- {
- uint32_t *base = &voodoo->texture_cache[tmu][c].data[texture_offset[lod]];
- uint32_t tex_addr = params->tex_base[tmu][lod] & voodoo->texture_mask;
- int x, y;
- int shift = 8 - params->tex_lod[tmu][lod];
- rgba_u *pal;
-
- //pclog(" LOD %i : %08x - %08x %i %i,%i\n", lod, params->tex_base[tmu][lod] & voodoo->texture_mask, addr, voodoo->params.tformat[tmu], voodoo->params.tex_w_mask[tmu][lod],voodoo->params.tex_h_mask[tmu][lod]);
-
-
- switch (params->tformat[tmu])
- {
- case TEX_RGB332:
- for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
- {
- for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
- {
- uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
-
- base[x] = makergba(rgb332[dat].r, rgb332[dat].g, rgb332[dat].b, 0xff);
- }
- tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
- base += (1 << shift);
- }
- break;
-
- case TEX_Y4I2Q2:
- pal = voodoo->ncc_lookup[tmu][(voodoo->params.textureMode[tmu] & TEXTUREMODE_NCC_SEL) ? 1 : 0];
- for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
- {
- for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
- {
- uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
-
- base[x] = makergba(pal[dat].rgba.r, pal[dat].rgba.g, pal[dat].rgba.b, 0xff);
- }
- tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
- base += (1 << shift);
- }
- break;
-
- case TEX_A8:
- for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
- {
- for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
- {
- uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
-
- base[x] = makergba(dat, dat, dat, dat);
- }
- tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
- base += (1 << shift);
- }
- break;
-
- case TEX_I8:
- for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
- {
- for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
- {
- uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
-
- base[x] = makergba(dat, dat, dat, 0xff);
- }
- tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
- base += (1 << shift);
- }
- break;
-
- case TEX_AI8:
- for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
- {
- for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
- {
- uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
-
- base[x] = makergba((dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0xf0) | ((dat >> 4) & 0x0f));
- }
- tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
- base += (1 << shift);
- }
- break;
-
- case TEX_PAL8:
- pal = voodoo->palette[tmu];
- for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
- {
- for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
- {
- uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
-
- base[x] = makergba(pal[dat].rgba.r, pal[dat].rgba.g, pal[dat].rgba.b, 0xff);
- }
- tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
- base += (1 << shift);
- }
- break;
-
- case TEX_APAL8:
- pal = voodoo->palette[tmu];
- for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
- {
- for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
- {
- uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
-
- int r = ((pal[dat].rgba.r & 3) << 6) | ((pal[dat].rgba.g & 0xf0) >> 2) | (pal[dat].rgba.r & 3);
- int g = ((pal[dat].rgba.g & 0xf) << 4) | ((pal[dat].rgba.b & 0xc0) >> 4) | ((pal[dat].rgba.g & 0xf) >> 2);
- int b = ((pal[dat].rgba.b & 0x3f) << 2) | ((pal[dat].rgba.b & 0x30) >> 4);
- int a = (pal[dat].rgba.r & 0xfc) | ((pal[dat].rgba.r & 0xc0) >> 6);
-
- base[x] = makergba(r, g, b, a);
- }
- tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
- base += (1 << shift);
- }
- break;
-
- case TEX_ARGB8332:
- for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
- {
- for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
- {
- uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
-
- base[x] = makergba(rgb332[dat & 0xff].r, rgb332[dat & 0xff].g, rgb332[dat & 0xff].b, dat >> 8);
- }
- tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
- base += (1 << shift);
- }
- break;
-
- case TEX_A8Y4I2Q2:
- pal = voodoo->ncc_lookup[tmu][(voodoo->params.textureMode[tmu] & TEXTUREMODE_NCC_SEL) ? 1 : 0];
- for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
- {
- for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
- {
- uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
-
- base[x] = makergba(pal[dat & 0xff].rgba.r, pal[dat & 0xff].rgba.g, pal[dat & 0xff].rgba.b, dat >> 8);
- }
- tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
- base += (1 << shift);
- }
- break;
-
- case TEX_R5G6B5:
- for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
- {
- for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
- {
- uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
-
- base[x] = makergba(rgb565[dat].r, rgb565[dat].g, rgb565[dat].b, 0xff);
- }
- tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
- base += (1 << shift);
- }
- break;
-
- case TEX_ARGB1555:
- for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
- {
- for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
- {
- uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
-
- base[x] = makergba(argb1555[dat].r, argb1555[dat].g, argb1555[dat].b, argb1555[dat].a);
- }
- tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
- base += (1 << shift);
- }
- break;
-
- case TEX_ARGB4444:
- for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
- {
- for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
- {
- uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
-
- base[x] = makergba(argb4444[dat].r, argb4444[dat].g, argb4444[dat].b, argb4444[dat].a);
- }
- tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
- base += (1 << shift);
- }
- break;
-
- case TEX_A8I8:
- for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
- {
- for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
- {
- uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
-
- base[x] = makergba(dat & 0xff, dat & 0xff, dat & 0xff, dat >> 8);
- }
- tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
- base += (1 << shift);
- }
- break;
-
- case TEX_APAL88:
- pal = voodoo->palette[tmu];
- for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
- {
- for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
- {
- uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
-
- base[x] = makergba(pal[dat & 0xff].rgba.r, pal[dat & 0xff].rgba.g, pal[dat & 0xff].rgba.b, dat >> 8);
- }
- tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
- base += (1 << shift);
- }
- break;
-
- default:
- fatal("Unknown texture format %i\n", params->tformat[tmu]);
- }
- }
-
- voodoo->texture_cache[tmu][c].is16 = voodoo->params.tformat[tmu] & 8;
-
- if (params->tformat[tmu] == TEX_PAL8 || params->tformat[tmu] == TEX_APAL8 || params->tformat[tmu] == TEX_APAL88)
- voodoo->texture_cache[tmu][c].palette_checksum = palette_checksum;
- else
- voodoo->texture_cache[tmu][c].palette_checksum = 0;
-
- if (lod_min == 0)
- {
- voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->params.tex_base[tmu][0];
- voodoo->texture_cache[tmu][c].addr_end[0] = voodoo->params.tex_end[tmu][0];
- }
- else
- voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->texture_cache[tmu][c].addr_end[0] = 0;
-
- if (lod_min <= 1 && lod_max >= 1)
- {
- voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->params.tex_base[tmu][1];
- voodoo->texture_cache[tmu][c].addr_end[1] = voodoo->params.tex_end[tmu][1];
- }
- else
- voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->texture_cache[tmu][c].addr_end[1] = 0;
-
- if (lod_min <= 2 && lod_max >= 2)
- {
- voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->params.tex_base[tmu][2];
- voodoo->texture_cache[tmu][c].addr_end[2] = voodoo->params.tex_end[tmu][2];
- }
- else
- voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->texture_cache[tmu][c].addr_end[2] = 0;
-
- if (lod_max >= 3)
- {
- voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->params.tex_base[tmu][(lod_min > 3) ? lod_min : 3];
- voodoo->texture_cache[tmu][c].addr_end[3] = voodoo->params.tex_end[tmu][(lod_max < 8) ? lod_max : 8];
- }
- else
- voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->texture_cache[tmu][c].addr_end[3] = 0;
-
-
- for (d = 0; d < 4; d++)
- {
- addr = voodoo->texture_cache[tmu][c].addr_start[d];
- addr_end = voodoo->texture_cache[tmu][c].addr_end[d];
-
- if (addr_end != 0)
- {
- for (; addr <= addr_end; addr += (1 << TEX_DIRTY_SHIFT))
- voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1;
- }
- }
-
- params->tex_entry[tmu] = c;
- voodoo->texture_cache[tmu][c].refcount++;
-}
-
-static void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu)
-{
- int wait_for_idle = 0;
- int c;
-
- memset(voodoo->texture_present[tmu], 0, sizeof(voodoo->texture_present[0]));
-// pclog("Evict %08x %i\n", dirty_addr, sizeof(voodoo->texture_present));
- for (c = 0; c < TEX_CACHE_MAX; c++)
- {
- if (voodoo->texture_cache[tmu][c].base != -1)
- {
- int d;
-
- for (d = 0; d < 4; d++)
- {
- int addr_start = voodoo->texture_cache[tmu][c].addr_start[d];
- int addr_end = voodoo->texture_cache[tmu][c].addr_end[d];
-
- if (addr_end != 0)
- {
- int addr_start_masked = addr_start & voodoo->texture_mask & ~0x3ff;
- int addr_end_masked = ((addr_end & voodoo->texture_mask) + 0x3ff) & ~0x3ff;
-
- if (addr_end_masked < addr_start_masked)
- addr_end_masked = voodoo->texture_mask+1;
- if (dirty_addr >= addr_start_masked && dirty_addr < addr_end_masked)
- {
-// pclog(" Evict texture %i %08x\n", c, voodoo->texture_cache[tmu][c].base);
-
- if (voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[0] ||
- (voodoo->render_threads == 2 && voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[1]))
- wait_for_idle = 1;
-
- voodoo->texture_cache[tmu][c].base = -1;
- }
- else
- {
- for (; addr_start <= addr_end; addr_start += (1 << TEX_DIRTY_SHIFT))
- voodoo->texture_present[tmu][(addr_start & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1;
- }
- }
- }
- }
- }
- if (wait_for_idle)
- wait_for_render_thread_idle(voodoo);
-}
-
-typedef struct voodoo_state_t
-{
- int xstart, xend, xdir;
- uint32_t base_r, base_g, base_b, base_a, base_z;
- struct
- {
- int64_t base_s, base_t, base_w;
- int lod;
- } tmu[2];
- int64_t base_w;
- int lod;
- int lod_min[2], lod_max[2];
- int dx1, dx2;
- int y, yend, ydir;
- int32_t dxAB, dxAC, dxBC;
- int tex_b[2], tex_g[2], tex_r[2], tex_a[2];
- int tex_s, tex_t;
- int clamp_s[2], clamp_t[2];
-
- int32_t vertexAx, vertexAy, vertexBx, vertexBy, vertexCx, vertexCy;
-
- uint32_t *tex[2][LOD_MAX+1];
- int tformat;
-
- int *tex_w_mask[2];
- int *tex_h_mask[2];
- int *tex_shift[2];
- int *tex_lod[2];
-
- uint16_t *fb_mem, *aux_mem;
-
- int32_t ib, ig, ir, ia;
- int32_t z;
-
- int32_t new_depth;
-
- int64_t tmu0_s, tmu0_t;
- int64_t tmu0_w;
- int64_t tmu1_s, tmu1_t;
- int64_t tmu1_w;
- int64_t w;
-
- int pixel_count, texel_count;
- int x, x2;
-
- uint32_t w_depth;
-
- float log_temp;
- uint32_t ebp_store;
- uint32_t texBaseAddr;
-
- int lod_frac[2];
-} voodoo_state_t;
-
-static int voodoo_output = 0;
-
-static uint8_t logtable[256] =
-{
- 0x00,0x01,0x02,0x04,0x05,0x07,0x08,0x09,0x0b,0x0c,0x0e,0x0f,0x10,0x12,0x13,0x15,
- 0x16,0x17,0x19,0x1a,0x1b,0x1d,0x1e,0x1f,0x21,0x22,0x23,0x25,0x26,0x27,0x28,0x2a,
- 0x2b,0x2c,0x2e,0x2f,0x30,0x31,0x33,0x34,0x35,0x36,0x38,0x39,0x3a,0x3b,0x3d,0x3e,
- 0x3f,0x40,0x41,0x43,0x44,0x45,0x46,0x47,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x50,0x51,
- 0x52,0x53,0x54,0x55,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x60,0x61,0x62,0x63,
- 0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,
- 0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x83,0x84,0x85,
- 0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,
- 0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,0xa0,0xa1,0xa2,0xa2,0xa3,
- 0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xad,0xae,0xaf,0xb0,0xb1,0xb2,
- 0xb3,0xb4,0xb5,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbc,0xbd,0xbe,0xbf,0xc0,
- 0xc1,0xc2,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xcd,
- 0xce,0xcf,0xd0,0xd1,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd6,0xd7,0xd8,0xd9,0xda,0xda,
- 0xdb,0xdc,0xdd,0xde,0xde,0xdf,0xe0,0xe1,0xe1,0xe2,0xe3,0xe4,0xe5,0xe5,0xe6,0xe7,
- 0xe8,0xe8,0xe9,0xea,0xeb,0xeb,0xec,0xed,0xee,0xef,0xef,0xf0,0xf1,0xf2,0xf2,0xf3,
- 0xf4,0xf5,0xf5,0xf6,0xf7,0xf7,0xf8,0xf9,0xfa,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff
-};
-
-static inline int fastlog(uint64_t val)
-{
- uint64_t oldval = val;
- int exp = 63;
- int frac;
-
- if (!val || val & (1ULL << 63))
- return 0x80000000;
-
- if (!(val & 0xffffffff00000000))
- {
- exp -= 32;
- val <<= 32;
- }
- if (!(val & 0xffff000000000000))
- {
- exp -= 16;
- val <<= 16;
- }
- if (!(val & 0xff00000000000000))
- {
- exp -= 8;
- val <<= 8;
- }
- if (!(val & 0xf000000000000000))
- {
- exp -= 4;
- val <<= 4;
- }
- if (!(val & 0xc000000000000000))
- {
- exp -= 2;
- val <<= 2;
- }
- if (!(val & 0x8000000000000000))
- {
- exp -= 1;
- val <<= 1;
- }
-
- if (exp >= 8)
- frac = (oldval >> (exp - 8)) & 0xff;
- else
- frac = (oldval << (8 - exp)) & 0xff;
-
- return (exp << 8) | logtable[frac];
-}
-
-static inline int voodoo_fls(uint16_t val)
-{
- int num = 0;
-
-//pclog("fls(%04x) = ", val);
- if (!(val & 0xff00))
- {
- num += 8;
- val <<= 8;
- }
- if (!(val & 0xf000))
- {
- num += 4;
- val <<= 4;
- }
- if (!(val & 0xc000))
- {
- num += 2;
- val <<= 2;
- }
- if (!(val & 0x8000))
- {
- num += 1;
- val <<= 1;
- }
-//pclog("%i %04x\n", num, val);
- return num;
-}
-
-typedef struct voodoo_texture_state_t
-{
- int s, t;
- int w_mask, h_mask;
- int tex_shift;
-} voodoo_texture_state_t;
-
-static inline void tex_read(voodoo_state_t *state, voodoo_texture_state_t *texture_state, int tmu)
-{
- uint32_t dat;
-
- if (texture_state->s & ~texture_state->w_mask)
- {
- if (state->clamp_s[tmu])
- {
- if (texture_state->s < 0)
- texture_state->s = 0;
- if (texture_state->s > texture_state->w_mask)
- texture_state->s = texture_state->w_mask;
- }
- else
- texture_state->s &= texture_state->w_mask;
- }
- if (texture_state->t & ~texture_state->h_mask)
- {
- if (state->clamp_t[tmu])
- {
- if (texture_state->t < 0)
- texture_state->t = 0;
- if (texture_state->t > texture_state->h_mask)
- texture_state->t = texture_state->h_mask;
- }
- else
- texture_state->t &= texture_state->h_mask;
- }
-
- dat = state->tex[tmu][state->lod][texture_state->s + (texture_state->t << texture_state->tex_shift)];
-
- state->tex_b[tmu] = dat & 0xff;
- state->tex_g[tmu] = (dat >> 8) & 0xff;
- state->tex_r[tmu] = (dat >> 16) & 0xff;
- state->tex_a[tmu] = (dat >> 24) & 0xff;
-}
-
-#define LOW4(x) ((x & 0x0f) | ((x & 0x0f) << 4))
-#define HIGH4(x) ((x & 0xf0) | ((x & 0xf0) >> 4))
-
-static inline void tex_read_4(voodoo_state_t *state, voodoo_texture_state_t *texture_state, int s, int t, int *d, int tmu, int x)
-{
- rgba_u dat[4];
-
- if (((s | (s + 1)) & ~texture_state->w_mask) || ((t | (t + 1)) & ~texture_state->h_mask))
- {
- int c;
- for (c = 0; c < 4; c++)
- {
- int _s = s + (c & 1);
- int _t = t + ((c & 2) >> 1);
-
- if (_s & ~texture_state->w_mask)
- {
- if (state->clamp_s[tmu])
- {
- if (_s < 0)
- _s = 0;
- if (_s > texture_state->w_mask)
- _s = texture_state->w_mask;
- }
- else
- _s &= texture_state->w_mask;
- }
- if (_t & ~texture_state->h_mask)
- {
- if (state->clamp_t[tmu])
- {
- if (_t < 0)
- _t = 0;
- if (_t > texture_state->h_mask)
- _t = texture_state->h_mask;
- }
- else
- _t &= texture_state->h_mask;
- }
- dat[c].u = state->tex[tmu][state->lod][_s + (_t << texture_state->tex_shift)];
- }
- }
- else
- {
- dat[0].u = state->tex[tmu][state->lod][s + (t << texture_state->tex_shift)];
- dat[1].u = state->tex[tmu][state->lod][s + 1 + (t << texture_state->tex_shift)];
- dat[2].u = state->tex[tmu][state->lod][s + ((t + 1) << texture_state->tex_shift)];
- dat[3].u = state->tex[tmu][state->lod][s + 1 + ((t + 1) << texture_state->tex_shift)];
- }
-
- state->tex_r[tmu] = (dat[0].rgba.r * d[0] + dat[1].rgba.r * d[1] + dat[2].rgba.r * d[2] + dat[3].rgba.r * d[3]) >> 8;
- state->tex_g[tmu] = (dat[0].rgba.g * d[0] + dat[1].rgba.g * d[1] + dat[2].rgba.g * d[2] + dat[3].rgba.g * d[3]) >> 8;
- state->tex_b[tmu] = (dat[0].rgba.b * d[0] + dat[1].rgba.b * d[1] + dat[2].rgba.b * d[2] + dat[3].rgba.b * d[3]) >> 8;
- state->tex_a[tmu] = (dat[0].rgba.a * d[0] + dat[1].rgba.a * d[1] + dat[2].rgba.a * d[2] + dat[3].rgba.a * d[3]) >> 8;
-}
-
-static inline void voodoo_get_texture(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int tmu, int x)
-{
- voodoo_texture_state_t texture_state;
- int d[4];
- int s, t;
- int tex_lod = state->tex_lod[tmu][state->lod];
-
- texture_state.w_mask = state->tex_w_mask[tmu][state->lod];
- texture_state.h_mask = state->tex_h_mask[tmu][state->lod];
- texture_state.tex_shift = 8 - tex_lod;
-
- if (params->tLOD[tmu] & LOD_TMIRROR_S)
- {
- if (state->tex_s & 0x1000)
- state->tex_s = ~state->tex_s;
- }
- if (params->tLOD[tmu] & LOD_TMIRROR_T)
- {
- if (state->tex_t & 0x1000)
- state->tex_t = ~state->tex_t;
- }
-
- if (voodoo->bilinear_enabled && params->textureMode[tmu] & 6)
- {
- int _ds, dt;
-
- state->tex_s -= 1 << (3+tex_lod);
- state->tex_t -= 1 << (3+tex_lod);
-
- s = state->tex_s >> tex_lod;
- t = state->tex_t >> tex_lod;
-
- _ds = s & 0xf;
- dt = t & 0xf;
-
- s >>= 4;
- t >>= 4;
-//if (x == 80)
-//if (voodoo_output)
-// pclog("s=%08x t=%08x _ds=%02x _dt=%02x\n", s, t, _ds, dt);
- d[0] = (16 - _ds) * (16 - dt);
- d[1] = _ds * (16 - dt);
- d[2] = (16 - _ds) * dt;
- d[3] = _ds * dt;
-
-// texture_state.s = s;
-// texture_state.t = t;
- tex_read_4(state, &texture_state, s, t, d, tmu, x);
-
-
-/* state->tex_r = (tex_samples[0].rgba.r * d[0] + tex_samples[1].rgba.r * d[1] + tex_samples[2].rgba.r * d[2] + tex_samples[3].rgba.r * d[3]) >> 8;
- state->tex_g = (tex_samples[0].rgba.g * d[0] + tex_samples[1].rgba.g * d[1] + tex_samples[2].rgba.g * d[2] + tex_samples[3].rgba.g * d[3]) >> 8;
- state->tex_b = (tex_samples[0].rgba.b * d[0] + tex_samples[1].rgba.b * d[1] + tex_samples[2].rgba.b * d[2] + tex_samples[3].rgba.b * d[3]) >> 8;
- state->tex_a = (tex_samples[0].rgba.a * d[0] + tex_samples[1].rgba.a * d[1] + tex_samples[2].rgba.a * d[2] + tex_samples[3].rgba.a * d[3]) >> 8;*/
-/* state->tex_r = tex_samples[0].r;
- state->tex_g = tex_samples[0].g;
- state->tex_b = tex_samples[0].b;
- state->tex_a = tex_samples[0].a;*/
- }
- else
- {
- // rgba_t tex_samples;
- // voodoo_texture_state_t texture_state;
-// int s = state->tex_s >> (18+state->lod);
-// int t = state->tex_t >> (18+state->lod);
- // int s, t;
-
-// state->tex_s -= 1 << (17+state->lod);
-// state->tex_t -= 1 << (17+state->lod);
-
- s = state->tex_s >> (4+tex_lod);
- t = state->tex_t >> (4+tex_lod);
-
- texture_state.s = s;
- texture_state.t = t;
- tex_read(state, &texture_state, tmu);
-
-/* state->tex_r = tex_samples[0].rgba.r;
- state->tex_g = tex_samples[0].rgba.g;
- state->tex_b = tex_samples[0].rgba.b;
- state->tex_a = tex_samples[0].rgba.a;*/
- }
-}
-
-static inline void voodoo_tmu_fetch(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int tmu, int x)
-{
- if (params->textureMode[tmu] & 1)
- {
- int64_t _w = 0;
-
- if (tmu)
- {
- if (state->tmu1_w)
- _w = (int64_t)((1ULL << 48) / state->tmu1_w);
- state->tex_s = (int32_t)(((((state->tmu1_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30);
- state->tex_t = (int32_t)(((((state->tmu1_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30);
- }
- else
- {
- if (state->tmu0_w)
- _w = (int64_t)((1ULL << 48) / state->tmu0_w);
- state->tex_s = (int32_t)(((((state->tmu0_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30);
- state->tex_t = (int32_t)(((((state->tmu0_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30);
- }
-
- state->lod = state->tmu[tmu].lod + (fastlog(_w) - (19 << 8));
- }
- else
- {
- if (tmu)
- {
- state->tex_s = (int32_t)(state->tmu1_s >> (14+14));
- state->tex_t = (int32_t)(state->tmu1_t >> (14+14));
- }
- else
- {
- state->tex_s = (int32_t)(state->tmu0_s >> (14+14));
- state->tex_t = (int32_t)(state->tmu0_t >> (14+14));
- }
- state->lod = state->tmu[tmu].lod;
- }
-
- if (state->lod < state->lod_min[tmu])
- state->lod = state->lod_min[tmu];
- else if (state->lod > state->lod_max[tmu])
- state->lod = state->lod_max[tmu];
- state->lod_frac[tmu] = state->lod & 0xff;
- state->lod >>= 8;
-
- voodoo_get_texture(voodoo, params, state, tmu, x);
-}
-
-#define DEPTH_TEST(comp_depth) \
- do \
- { \
- switch (depth_op) \
- { \
- case DEPTHOP_NEVER: \
- voodoo->fbiZFuncFail++; \
- goto skip_pixel; \
- case DEPTHOP_LESSTHAN: \
- if (!(comp_depth < old_depth)) \
- { \
- voodoo->fbiZFuncFail++; \
- goto skip_pixel; \
- } \
- break; \
- case DEPTHOP_EQUAL: \
- if (!(comp_depth == old_depth)) \
- { \
- voodoo->fbiZFuncFail++; \
- goto skip_pixel; \
- } \
- break; \
- case DEPTHOP_LESSTHANEQUAL: \
- if (!(comp_depth <= old_depth)) \
- { \
- voodoo->fbiZFuncFail++; \
- goto skip_pixel; \
- } \
- break; \
- case DEPTHOP_GREATERTHAN: \
- if (!(comp_depth > old_depth)) \
- { \
- voodoo->fbiZFuncFail++; \
- goto skip_pixel; \
- } \
- break; \
- case DEPTHOP_NOTEQUAL: \
- if (!(comp_depth != old_depth)) \
- { \
- voodoo->fbiZFuncFail++; \
- goto skip_pixel; \
- } \
- break; \
- case DEPTHOP_GREATERTHANEQUAL: \
- if (!(comp_depth >= old_depth)) \
- { \
- voodoo->fbiZFuncFail++; \
- goto skip_pixel; \
- } \
- break; \
- case DEPTHOP_ALWAYS: \
- break; \
- } \
- } while (0)
-
-#define APPLY_FOG(src_r, src_g, src_b, z, ia, w) \
- do \
- { \
- if (params->fogMode & FOG_CONSTANT) \
- { \
- src_r += params->fogColor.r; \
- src_g += params->fogColor.g; \
- src_b += params->fogColor.b; \
- } \
- else \
- { \
- int fog_r, fog_g, fog_b, fog_a = 0; \
- int fog_idx; \
- \
- if (!(params->fogMode & FOG_ADD)) \
- { \
- fog_r = params->fogColor.r; \
- fog_g = params->fogColor.g; \
- fog_b = params->fogColor.b; \
- } \
- else \
- fog_r = fog_g = fog_b = 0; \
- \
- if (!(params->fogMode & FOG_MULT)) \
- { \
- fog_r -= src_r; \
- fog_g -= src_g; \
- fog_b -= src_b; \
- } \
- \
- switch (params->fogMode & (FOG_Z|FOG_ALPHA)) \
- { \
- case 0: \
- fog_idx = (w_depth >> 10) & 0x3f; \
- \
- fog_a = params->fogTable[fog_idx].fog; \
- fog_a += (params->fogTable[fog_idx].dfog * ((w_depth >> 2) & 0xff)) >> 10; \
- break; \
- case FOG_Z: \
- fog_a = (z >> 20) & 0xff; \
- break; \
- case FOG_ALPHA: \
- fog_a = CLAMP(ia >> 12); \
- break; \
- case FOG_W: \
- fog_a = CLAMP((w >> 32) & 0xff); \
- break; \
- } \
- fog_a++; \
- \
- fog_r = (fog_r * fog_a) >> 8; \
- fog_g = (fog_g * fog_a) >> 8; \
- fog_b = (fog_b * fog_a) >> 8; \
- \
- if (params->fogMode & FOG_MULT) \
- { \
- src_r = fog_r; \
- src_g = fog_g; \
- src_b = fog_b; \
- } \
- else \
- { \
- src_r += fog_r; \
- src_g += fog_g; \
- src_b += fog_b; \
- } \
- } \
- \
- src_r = CLAMP(src_r); \
- src_g = CLAMP(src_g); \
- src_b = CLAMP(src_b); \
- } while (0)
-
-#define ALPHA_TEST(src_a) \
- do \
- { \
- switch (alpha_func) \
- { \
- case AFUNC_NEVER: \
- voodoo->fbiAFuncFail++; \
- goto skip_pixel; \
- case AFUNC_LESSTHAN: \
- if (!(src_a < a_ref)) \
- { \
- voodoo->fbiAFuncFail++; \
- goto skip_pixel; \
- } \
- break; \
- case AFUNC_EQUAL: \
- if (!(src_a == a_ref)) \
- { \
- voodoo->fbiAFuncFail++; \
- goto skip_pixel; \
- } \
- break; \
- case AFUNC_LESSTHANEQUAL: \
- if (!(src_a <= a_ref)) \
- { \
- voodoo->fbiAFuncFail++; \
- goto skip_pixel; \
- } \
- break; \
- case AFUNC_GREATERTHAN: \
- if (!(src_a > a_ref)) \
- { \
- voodoo->fbiAFuncFail++; \
- goto skip_pixel; \
- } \
- break; \
- case AFUNC_NOTEQUAL: \
- if (!(src_a != a_ref)) \
- { \
- voodoo->fbiAFuncFail++; \
- goto skip_pixel; \
- } \
- break; \
- case AFUNC_GREATERTHANEQUAL: \
- if (!(src_a >= a_ref)) \
- { \
- voodoo->fbiAFuncFail++; \
- goto skip_pixel; \
- } \
- break; \
- case AFUNC_ALWAYS: \
- break; \
- } \
- } while (0)
-
-#define ALPHA_BLEND(src_r, src_g, src_b, src_a) \
- do \
- { \
- int _a; \
- int newdest_r = 0, newdest_g = 0, newdest_b = 0; \
- \
- switch (dest_afunc) \
- { \
- case AFUNC_AZERO: \
- newdest_r = newdest_g = newdest_b = 0; \
- break; \
- case AFUNC_ASRC_ALPHA: \
- newdest_r = (dest_r * src_a) / 255; \
- newdest_g = (dest_g * src_a) / 255; \
- newdest_b = (dest_b * src_a) / 255; \
- break; \
- case AFUNC_A_COLOR: \
- newdest_r = (dest_r * src_r) / 255; \
- newdest_g = (dest_g * src_g) / 255; \
- newdest_b = (dest_b * src_b) / 255; \
- break; \
- case AFUNC_ADST_ALPHA: \
- newdest_r = (dest_r * dest_a) / 255; \
- newdest_g = (dest_g * dest_a) / 255; \
- newdest_b = (dest_b * dest_a) / 255; \
- break; \
- case AFUNC_AONE: \
- newdest_r = dest_r; \
- newdest_g = dest_g; \
- newdest_b = dest_b; \
- break; \
- case AFUNC_AOMSRC_ALPHA: \
- newdest_r = (dest_r * (255-src_a)) / 255; \
- newdest_g = (dest_g * (255-src_a)) / 255; \
- newdest_b = (dest_b * (255-src_a)) / 255; \
- break; \
- case AFUNC_AOM_COLOR: \
- newdest_r = (dest_r * (255-src_r)) / 255; \
- newdest_g = (dest_g * (255-src_g)) / 255; \
- newdest_b = (dest_b * (255-src_b)) / 255; \
- break; \
- case AFUNC_AOMDST_ALPHA: \
- newdest_r = (dest_r * (255-dest_a)) / 255; \
- newdest_g = (dest_g * (255-dest_a)) / 255; \
- newdest_b = (dest_b * (255-dest_a)) / 255; \
- break; \
- case AFUNC_ASATURATE: \
- _a = MIN(src_a, 1-dest_a); \
- newdest_r = (dest_r * _a) / 255; \
- newdest_g = (dest_g * _a) / 255; \
- newdest_b = (dest_b * _a) / 255; \
- break; \
- } \
- \
- switch (src_afunc) \
- { \
- case AFUNC_AZERO: \
- src_r = src_g = src_b = 0; \
- break; \
- case AFUNC_ASRC_ALPHA: \
- src_r = (src_r * src_a) / 255; \
- src_g = (src_g * src_a) / 255; \
- src_b = (src_b * src_a) / 255; \
- break; \
- case AFUNC_A_COLOR: \
- src_r = (src_r * dest_r) / 255; \
- src_g = (src_g * dest_g) / 255; \
- src_b = (src_b * dest_b) / 255; \
- break; \
- case AFUNC_ADST_ALPHA: \
- src_r = (src_r * dest_a) / 255; \
- src_g = (src_g * dest_a) / 255; \
- src_b = (src_b * dest_a) / 255; \
- break; \
- case AFUNC_AONE: \
- break; \
- case AFUNC_AOMSRC_ALPHA: \
- src_r = (src_r * (255-src_a)) / 255; \
- src_g = (src_g * (255-src_a)) / 255; \
- src_b = (src_b * (255-src_a)) / 255; \
- break; \
- case AFUNC_AOM_COLOR: \
- src_r = (src_r * (255-dest_r)) / 255; \
- src_g = (src_g * (255-dest_g)) / 255; \
- src_b = (src_b * (255-dest_b)) / 255; \
- break; \
- case AFUNC_AOMDST_ALPHA: \
- src_r = (src_r * (255-dest_a)) / 255; \
- src_g = (src_g * (255-dest_a)) / 255; \
- src_b = (src_b * (255-dest_a)) / 255; \
- break; \
- case AFUNC_ACOLORBEFOREFOG: \
- fatal("AFUNC_ACOLORBEFOREFOG\n"); \
- break; \
- } \
- \
- src_r += newdest_r; \
- src_g += newdest_g; \
- src_b += newdest_b; \
- \
- src_r = CLAMP(src_r); \
- src_g = CLAMP(src_g); \
- src_b = CLAMP(src_b); \
- } while(0)
-
-
-#define _rgb_sel ( params->fbzColorPath & 3)
-#define a_sel ( (params->fbzColorPath >> 2) & 3)
-#define cc_localselect ( params->fbzColorPath & (1 << 4))
-#define cca_localselect ( (params->fbzColorPath >> 5) & 3)
-#define cc_localselect_override ( params->fbzColorPath & (1 << 7))
-#define cc_zero_other ( params->fbzColorPath & (1 << 8))
-#define cc_sub_clocal ( params->fbzColorPath & (1 << 9))
-#define cc_mselect ( (params->fbzColorPath >> 10) & 7)
-#define cc_reverse_blend ( params->fbzColorPath & (1 << 13))
-#define cc_add ( (params->fbzColorPath >> 14) & 3)
-#define cc_add_alocal ( params->fbzColorPath & (1 << 15))
-#define cc_invert_output ( params->fbzColorPath & (1 << 16))
-#define cca_zero_other ( params->fbzColorPath & (1 << 17))
-#define cca_sub_clocal ( params->fbzColorPath & (1 << 18))
-#define cca_mselect ( (params->fbzColorPath >> 19) & 7)
-#define cca_reverse_blend ( params->fbzColorPath & (1 << 22))
-#define cca_add ( (params->fbzColorPath >> 23) & 3)
-#define cca_invert_output ( params->fbzColorPath & (1 << 25))
-#define tc_zero_other (params->textureMode[0] & (1 << 12))
-#define tc_sub_clocal (params->textureMode[0] & (1 << 13))
-#define tc_mselect ((params->textureMode[0] >> 14) & 7)
-#define tc_reverse_blend (params->textureMode[0] & (1 << 17))
-#define tc_add_clocal (params->textureMode[0] & (1 << 18))
-#define tc_add_alocal (params->textureMode[0] & (1 << 19))
-#define tc_invert_output (params->textureMode[0] & (1 << 20))
-#define tca_zero_other (params->textureMode[0] & (1 << 21))
-#define tca_sub_clocal (params->textureMode[0] & (1 << 22))
-#define tca_mselect ((params->textureMode[0] >> 23) & 7)
-#define tca_reverse_blend (params->textureMode[0] & (1 << 26))
-#define tca_add_clocal (params->textureMode[0] & (1 << 27))
-#define tca_add_alocal (params->textureMode[0] & (1 << 28))
-#define tca_invert_output (params->textureMode[0] & (1 << 29))
-
-#define tc_sub_clocal_1 (params->textureMode[1] & (1 << 13))
-#define tc_mselect_1 ((params->textureMode[1] >> 14) & 7)
-#define tc_reverse_blend_1 (params->textureMode[1] & (1 << 17))
-#define tc_add_clocal_1 (params->textureMode[1] & (1 << 18))
-#define tc_add_alocal_1 (params->textureMode[1] & (1 << 19))
-#define tca_sub_clocal_1 (params->textureMode[1] & (1 << 22))
-#define tca_mselect_1 ((params->textureMode[1] >> 23) & 7)
-#define tca_reverse_blend_1 (params->textureMode[1] & (1 << 26))
-#define tca_add_clocal_1 (params->textureMode[1] & (1 << 27))
-#define tca_add_alocal_1 (params->textureMode[1] & (1 << 28))
-
-#define src_afunc ( (params->alphaMode >> 8) & 0xf)
-#define dest_afunc ( (params->alphaMode >> 12) & 0xf)
-#define alpha_func ( (params->alphaMode >> 1) & 7)
-#define a_ref ( params->alphaMode >> 24)
-#define depth_op ( (params->fbzMode >> 5) & 7)
-#define dither ( params->fbzMode & FBZ_DITHER)
-#define dither2x2 (params->fbzMode & FBZ_DITHER_2x2)
-
-/*Perform texture fetch and blending for both TMUs*/
-static inline void voodoo_tmu_fetch_and_blend(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int x)
-{
- int r,g,b,a;
- int c_reverse, a_reverse;
-// int c_reverse1, a_reverse1;
- int factor_r = 0, factor_g = 0, factor_b = 0, factor_a = 0;
-
- voodoo_tmu_fetch(voodoo, params, state, 1, x);
-
- if ((params->textureMode[1] & TEXTUREMODE_TRILINEAR) && (state->lod & 1))
- {
- c_reverse = tc_reverse_blend;
- a_reverse = tca_reverse_blend;
- }
- else
- {
- c_reverse = !tc_reverse_blend;
- a_reverse = !tca_reverse_blend;
- }
-/* c_reverse1 = c_reverse;
- a_reverse1 = a_reverse;*/
- if (tc_sub_clocal_1)
- {
- switch (tc_mselect_1)
- {
- case TC_MSELECT_ZERO:
- factor_r = factor_g = factor_b = 0;
- break;
- case TC_MSELECT_CLOCAL:
- factor_r = state->tex_r[1];
- factor_g = state->tex_g[1];
- factor_b = state->tex_b[1];
- break;
- case TC_MSELECT_AOTHER:
- factor_r = factor_g = factor_b = 0;
- break;
- case TC_MSELECT_ALOCAL:
- factor_r = factor_g = factor_b = state->tex_a[1];
- break;
- case TC_MSELECT_DETAIL:
- factor_r = (params->detail_bias[1] - state->lod) << params->detail_scale[1];
- if (factor_r > params->detail_max[1])
- factor_r = params->detail_max[1];
- factor_g = factor_b = factor_r;
- break;
- case TC_MSELECT_LOD_FRAC:
- factor_r = factor_g = factor_b = state->lod_frac[1];
- break;
- }
- if (!c_reverse)
- {
- r = (-state->tex_r[1] * (factor_r + 1)) >> 8;
- g = (-state->tex_g[1] * (factor_g + 1)) >> 8;
- b = (-state->tex_b[1] * (factor_b + 1)) >> 8;
- }
- else
- {
- r = (-state->tex_r[1] * ((factor_r^0xff) + 1)) >> 8;
- g = (-state->tex_g[1] * ((factor_g^0xff) + 1)) >> 8;
- b = (-state->tex_b[1] * ((factor_b^0xff) + 1)) >> 8;
- }
- if (tc_add_clocal_1)
- {
- r += state->tex_r[1];
- g += state->tex_g[1];
- b += state->tex_b[1];
- }
- else if (tc_add_alocal_1)
- {
- r += state->tex_a[1];
- g += state->tex_a[1];
- b += state->tex_a[1];
- }
- state->tex_r[1] = CLAMP(r);
- state->tex_g[1] = CLAMP(g);
- state->tex_b[1] = CLAMP(b);
- }
- if (tca_sub_clocal_1)
- {
- switch (tca_mselect_1)
- {
- case TCA_MSELECT_ZERO:
- factor_a = 0;
- break;
- case TCA_MSELECT_CLOCAL:
- factor_a = state->tex_a[1];
- break;
- case TCA_MSELECT_AOTHER:
- factor_a = 0;
- break;
- case TCA_MSELECT_ALOCAL:
- factor_a = state->tex_a[1];
- break;
- case TCA_MSELECT_DETAIL:
- factor_a = (params->detail_bias[1] - state->lod) << params->detail_scale[1];
- if (factor_a > params->detail_max[1])
- factor_a = params->detail_max[1];
- break;
- case TCA_MSELECT_LOD_FRAC:
- factor_a = state->lod_frac[1];
- break;
- }
- if (!a_reverse)
- a = (-state->tex_a[1] * ((factor_a ^ 0xff) + 1)) >> 8;
- else
- a = (-state->tex_a[1] * (factor_a + 1)) >> 8;
- if (tca_add_clocal_1 || tca_add_alocal_1)
- a += state->tex_a[1];
- state->tex_a[1] = CLAMP(a);
- }
-
-
- voodoo_tmu_fetch(voodoo, params, state, 0, x);
-
- if ((params->textureMode[0] & TEXTUREMODE_TRILINEAR) && (state->lod & 1))
- {
- c_reverse = tc_reverse_blend;
- a_reverse = tca_reverse_blend;
- }
- else
- {
- c_reverse = !tc_reverse_blend;
- a_reverse = !tca_reverse_blend;
- }
-
- if (!tc_zero_other)
- {
- r = state->tex_r[1];
- g = state->tex_g[1];
- b = state->tex_b[1];
- }
- else
- r = g = b = 0;
- if (tc_sub_clocal)
- {
- r -= state->tex_r[0];
- g -= state->tex_g[0];
- b -= state->tex_b[0];
- }
- switch (tc_mselect)
- {
- case TC_MSELECT_ZERO:
- factor_r = factor_g = factor_b = 0;
- break;
- case TC_MSELECT_CLOCAL:
- factor_r = state->tex_r[0];
- factor_g = state->tex_g[0];
- factor_b = state->tex_b[0];
- break;
- case TC_MSELECT_AOTHER:
- factor_r = factor_g = factor_b = state->tex_a[1];
- break;
- case TC_MSELECT_ALOCAL:
- factor_r = factor_g = factor_b = state->tex_a[0];
- break;
- case TC_MSELECT_DETAIL:
- factor_r = (params->detail_bias[0] - state->lod) << params->detail_scale[0];
- if (factor_r > params->detail_max[0])
- factor_r = params->detail_max[0];
- factor_g = factor_b = factor_r;
- break;
- case TC_MSELECT_LOD_FRAC:
- factor_r = factor_g = factor_b = state->lod_frac[0];
- break;
- }
- if (!c_reverse)
- {
- r = (r * (factor_r + 1)) >> 8;
- g = (g * (factor_g + 1)) >> 8;
- b = (b * (factor_b + 1)) >> 8;
- }
- else
- {
- r = (r * ((factor_r^0xff) + 1)) >> 8;
- g = (g * ((factor_g^0xff) + 1)) >> 8;
- b = (b * ((factor_b^0xff) + 1)) >> 8;
- }
- if (tc_add_clocal)
- {
- r += state->tex_r[0];
- g += state->tex_g[0];
- b += state->tex_b[0];
- }
- else if (tc_add_alocal)
- {
- r += state->tex_a[0];
- g += state->tex_a[0];
- b += state->tex_a[0];
- }
-
- if (!tca_zero_other)
- a = state->tex_a[1];
- else
- a = 0;
- if (tca_sub_clocal)
- a -= state->tex_a[0];
- switch (tca_mselect)
- {
- case TCA_MSELECT_ZERO:
- factor_a = 0;
- break;
- case TCA_MSELECT_CLOCAL:
- factor_a = state->tex_a[0];
- break;
- case TCA_MSELECT_AOTHER:
- factor_a = state->tex_a[1];
- break;
- case TCA_MSELECT_ALOCAL:
- factor_a = state->tex_a[0];
- break;
- case TCA_MSELECT_DETAIL:
- factor_a = (params->detail_bias[0] - state->lod) << params->detail_scale[0];
- if (factor_a > params->detail_max[0])
- factor_a = params->detail_max[0];
- break;
- case TCA_MSELECT_LOD_FRAC:
- factor_a = state->lod_frac[0];
- break;
- }
- if (a_reverse)
- a = (a * ((factor_a ^ 0xff) + 1)) >> 8;
- else
- a = (a * (factor_a + 1)) >> 8;
- if (tca_add_clocal || tca_add_alocal)
- a += state->tex_a[0];
-
-
- state->tex_r[0] = CLAMP(r);
- state->tex_g[0] = CLAMP(g);
- state->tex_b[0] = CLAMP(b);
- state->tex_a[0] = CLAMP(a);
-
- if (tc_invert_output)
- {
- state->tex_r[0] ^= 0xff;
- state->tex_g[0] ^= 0xff;
- state->tex_b[0] ^= 0xff;
- }
- if (tca_invert_output)
- state->tex_a[0] ^= 0xff;
-}
-
-#if (defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32) && !(defined __amd64__)
-#include "vid_voodoo_codegen_x86.h"
-#elif (defined __amd64__)
-#include "vid_voodoo_codegen_x86-64.h"
-#else
-#define NO_CODEGEN
-static int voodoo_recomp = 0;
-#endif
-
-static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int ystart, int yend, int odd_even)
-{
-/* int rgb_sel = params->fbzColorPath & 3;
- int a_sel = (params->fbzColorPath >> 2) & 3;
- int cc_localselect = params->fbzColorPath & (1 << 4);
- int cca_localselect = (params->fbzColorPath >> 5) & 3;
- int cc_localselect_override = params->fbzColorPath & (1 << 7);
- int cc_zero_other = params->fbzColorPath & (1 << 8);
- int cc_sub_clocal = params->fbzColorPath & (1 << 9);
- int cc_mselect = (params->fbzColorPath >> 10) & 7;
- int cc_reverse_blend = params->fbzColorPath & (1 << 13);
- int cc_add = (params->fbzColorPath >> 14) & 3;
- int cc_add_alocal = params->fbzColorPath & (1 << 15);
- int cc_invert_output = params->fbzColorPath & (1 << 16);
- int cca_zero_other = params->fbzColorPath & (1 << 17);
- int cca_sub_clocal = params->fbzColorPath & (1 << 18);
- int cca_mselect = (params->fbzColorPath >> 19) & 7;
- int cca_reverse_blend = params->fbzColorPath & (1 << 22);
- int cca_add = (params->fbzColorPath >> 23) & 3;
- int cca_invert_output = params->fbzColorPath & (1 << 25);
- int src_afunc = (params->alphaMode >> 8) & 0xf;
- int dest_afunc = (params->alphaMode >> 12) & 0xf;
- int alpha_func = (params->alphaMode >> 1) & 7;
- int a_ref = params->alphaMode >> 24;
- int depth_op = (params->fbzMode >> 5) & 7;
- int dither = params->fbzMode & FBZ_DITHER;*/
- int texels;
- int c;
-#ifndef NO_CODEGEN
- uint8_t (*voodoo_draw)(voodoo_state_t *state, voodoo_params_t *params, int x, int real_y);
-#endif
- int y_diff = SLI_ENABLED ? 2 : 1;
-
- if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH ||
- (params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL)
- texels = 1;
- else
- texels = 2;
-
- state->clamp_s[0] = params->textureMode[0] & TEXTUREMODE_TCLAMPS;
- state->clamp_t[0] = params->textureMode[0] & TEXTUREMODE_TCLAMPT;
- state->clamp_s[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPS;
- state->clamp_t[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPT;
-// int last_x;
-// pclog("voodoo_triangle : bottom-half %X %X %X %X %X %i %i %i %i\n", xstart, xend, dx1, dx2, dx2 * 36, xdir, y, yend, ydir);
-
- for (c = 0; c <= LOD_MAX; c++)
- {
- state->tex[0][c] = &voodoo->texture_cache[0][params->tex_entry[0]].data[texture_offset[c]];
- state->tex[1][c] = &voodoo->texture_cache[1][params->tex_entry[1]].data[texture_offset[c]];
- }
-
- state->tformat = params->tformat[0];
-
- state->tex_w_mask[0] = params->tex_w_mask[0];
- state->tex_h_mask[0] = params->tex_h_mask[0];
- state->tex_shift[0] = params->tex_shift[0];
- state->tex_lod[0] = params->tex_lod[0];
- state->tex_w_mask[1] = params->tex_w_mask[1];
- state->tex_h_mask[1] = params->tex_h_mask[1];
- state->tex_shift[1] = params->tex_shift[1];
- state->tex_lod[1] = params->tex_lod[1];
-
- if ((params->fbzMode & 1) && (ystart < params->clipLowY))
- {
- int dy = params->clipLowY - ystart;
-
- state->base_r += params->dRdY*dy;
- state->base_g += params->dGdY*dy;
- state->base_b += params->dBdY*dy;
- state->base_a += params->dAdY*dy;
- state->base_z += params->dZdY*dy;
- state->tmu[0].base_s += params->tmu[0].dSdY*dy;
- state->tmu[0].base_t += params->tmu[0].dTdY*dy;
- state->tmu[0].base_w += params->tmu[0].dWdY*dy;
- state->tmu[1].base_s += params->tmu[1].dSdY*dy;
- state->tmu[1].base_t += params->tmu[1].dTdY*dy;
- state->tmu[1].base_w += params->tmu[1].dWdY*dy;
- state->base_w += params->dWdY*dy;
- state->xstart += state->dx1*dy;
- state->xend += state->dx2*dy;
-
- ystart = params->clipLowY;
- }
-
- if ((params->fbzMode & 1) && (yend >= params->clipHighY))
- yend = params->clipHighY-1;
-
- state->y = ystart;
-// yend--;
-
- if (SLI_ENABLED)
- {
- int test_y;
-
- if (params->fbzMode & (1 << 17))
- test_y = (voodoo->v_disp-1) - state->y;
- else
- test_y = state->y;
-
- if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (test_y & 1)) ||
- ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(test_y & 1)))
- {
- state->y++;
-
- state->base_r += params->dRdY;
- state->base_g += params->dGdY;
- state->base_b += params->dBdY;
- state->base_a += params->dAdY;
- state->base_z += params->dZdY;
- state->tmu[0].base_s += params->tmu[0].dSdY;
- state->tmu[0].base_t += params->tmu[0].dTdY;
- state->tmu[0].base_w += params->tmu[0].dWdY;
- state->tmu[1].base_s += params->tmu[1].dSdY;
- state->tmu[1].base_t += params->tmu[1].dTdY;
- state->tmu[1].base_w += params->tmu[1].dWdY;
- state->base_w += params->dWdY;
- state->xstart += state->dx1;
- state->xend += state->dx2;
- }
- }
-#ifndef NO_CODEGEN
- if (voodoo->use_recompiler)
- voodoo_draw = voodoo_get_block(voodoo, params, state, odd_even);
- else
- voodoo_draw = NULL;
-#endif
-
- if (voodoo_output)
- pclog("dxAB=%08x dxBC=%08x dxAC=%08x\n", state->dxAB, state->dxBC, state->dxAC);
-// pclog("Start %i %i\n", ystart, voodoo->fbzMode & (1 << 17));
-
- for (; state->y < yend; state->y += y_diff)
- {
- int x, x2;
- int real_y = (state->y << 4) + 8;
- int start_x, start_x2;
- int dx;
- uint16_t *fb_mem, *aux_mem;
-
- state->ir = state->base_r;
- state->ig = state->base_g;
- state->ib = state->base_b;
- state->ia = state->base_a;
- state->z = state->base_z;
- state->tmu0_s = state->tmu[0].base_s;
- state->tmu0_t = state->tmu[0].base_t;
- state->tmu0_w = state->tmu[0].base_w;
- state->tmu1_s = state->tmu[1].base_s;
- state->tmu1_t = state->tmu[1].base_t;
- state->tmu1_w = state->tmu[1].base_w;
- state->w = state->base_w;
-
- x = (state->vertexAx << 12) + ((state->dxAC * (real_y - state->vertexAy)) >> 4);
-
- if (real_y < state->vertexBy)
- x2 = (state->vertexAx << 12) + ((state->dxAB * (real_y - state->vertexAy)) >> 4);
- else
- x2 = (state->vertexBx << 12) + ((state->dxBC * (real_y - state->vertexBy)) >> 4);
-
- if (params->fbzMode & (1 << 17))
- real_y = (voodoo->v_disp-1) - (real_y >> 4);
- else
- real_y >>= 4;
-
- if (SLI_ENABLED)
- {
- if (((real_y >> 1) & voodoo->odd_even_mask) != odd_even)
- goto next_line;
- }
- else
- {
- if ((real_y & voodoo->odd_even_mask) != odd_even)
- goto next_line;
- }
-
- start_x = x;
-
- if (state->xdir > 0)
- x2 -= (1 << 16);
- else
- x -= (1 << 16);
- dx = ((x + 0x7000) >> 16) - (((state->vertexAx << 12) + 0x7000) >> 16);
- start_x2 = x + 0x7000;
- x = (x + 0x7000) >> 16;
- x2 = (x2 + 0x7000) >> 16;
-
- if (voodoo_output)
- pclog("%03i:%03i : Ax=%08x start_x=%08x dSdX=%016llx dx=%08x s=%08x -> ", x, state->y, state->vertexAx << 8, start_x, params->tmu[0].dTdX, dx, state->tmu0_t);
-
- state->ir += (params->dRdX * dx);
- state->ig += (params->dGdX * dx);
- state->ib += (params->dBdX * dx);
- state->ia += (params->dAdX * dx);
- state->z += (params->dZdX * dx);
- state->tmu0_s += (params->tmu[0].dSdX * dx);
- state->tmu0_t += (params->tmu[0].dTdX * dx);
- state->tmu0_w += (params->tmu[0].dWdX * dx);
- state->tmu1_s += (params->tmu[1].dSdX * dx);
- state->tmu1_t += (params->tmu[1].dTdX * dx);
- state->tmu1_w += (params->tmu[1].dWdX * dx);
- state->w += (params->dWdX * dx);
-
- if (voodoo_output)
- pclog("%08llx %lli %lli\n", state->tmu0_t, state->tmu0_t >> (18+state->lod), (state->tmu0_t + (1 << (17+state->lod))) >> (18+state->lod));
-
- if (params->fbzMode & 1)
- {
- if (state->xdir > 0)
- {
- if (x < params->clipLeft)
- {
- int dx = params->clipLeft - x;
-
- state->ir += params->dRdX*dx;
- state->ig += params->dGdX*dx;
- state->ib += params->dBdX*dx;
- state->ia += params->dAdX*dx;
- state->z += params->dZdX*dx;
- state->tmu0_s += params->tmu[0].dSdX*dx;
- state->tmu0_t += params->tmu[0].dTdX*dx;
- state->tmu0_w += params->tmu[0].dWdX*dx;
- state->tmu1_s += params->tmu[1].dSdX*dx;
- state->tmu1_t += params->tmu[1].dTdX*dx;
- state->tmu1_w += params->tmu[1].dWdX*dx;
- state->w += params->dWdX*dx;
-
- x = params->clipLeft;
- }
- if (x2 >= params->clipRight)
- x2 = params->clipRight-1;
- }
- else
- {
- if (x >= params->clipRight)
- {
- int dx = (params->clipRight-1) - x;
-
- state->ir += params->dRdX*dx;
- state->ig += params->dGdX*dx;
- state->ib += params->dBdX*dx;
- state->ia += params->dAdX*dx;
- state->z += params->dZdX*dx;
- state->tmu0_s += params->tmu[0].dSdX*dx;
- state->tmu0_t += params->tmu[0].dTdX*dx;
- state->tmu0_w += params->tmu[0].dWdX*dx;
- state->tmu1_s += params->tmu[1].dSdX*dx;
- state->tmu1_t += params->tmu[1].dTdX*dx;
- state->tmu1_w += params->tmu[1].dWdX*dx;
- state->w += params->dWdX*dx;
-
- x = params->clipRight-1;
- }
- if (x2 < params->clipLeft)
- x2 = params->clipLeft;
- }
- }
-
- if (x2 < x && state->xdir > 0)
- goto next_line;
- if (x2 > x && state->xdir < 0)
- goto next_line;
-
- if (SLI_ENABLED)
- {
- state->fb_mem = fb_mem = (uint16_t *)&voodoo->fb_mem[params->draw_offset + ((real_y >> 1) * voodoo->row_width)];
- state->aux_mem = aux_mem = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + ((real_y >> 1) * voodoo->row_width)) & voodoo->fb_mask];
- }
- else
- {
- state->fb_mem = fb_mem = (uint16_t *)&voodoo->fb_mem[params->draw_offset + (real_y * voodoo->row_width)];
- state->aux_mem = aux_mem = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (real_y * voodoo->row_width)) & voodoo->fb_mask];
- }
-
- if (voodoo_output)
- pclog("%03i: x=%08x x2=%08x xstart=%08x xend=%08x dx=%08x start_x2=%08x\n", state->y, x, x2, state->xstart, state->xend, dx, start_x2);
-
- state->pixel_count = 0;
- state->texel_count = 0;
- state->x = x;
- state->x2 = x2;
-#ifndef NO_CODEGEN
- if (voodoo->use_recompiler)
- {
- voodoo_draw(state, params, x, real_y);
- }
- else
-#endif
- do
- {
- start_x = x;
- state->x = x;
- voodoo->pixel_count[odd_even]++;
- voodoo->texel_count[odd_even] += texels;
- voodoo->fbiPixelsIn++;
-
- if (voodoo_output)
- pclog(" X=%03i T=%08x\n", x, state->tmu0_t);
-// if (voodoo->fbzMode & FBZ_RGB_WMASK)
- {
- int update = 1;
- uint8_t cother_r, cother_g, cother_b, aother;
- uint8_t clocal_r, clocal_g, clocal_b, alocal;
- int src_r = 0, src_g = 0, src_b = 0, src_a = 0;
- int msel_r, msel_g, msel_b, msel_a;
- uint8_t dest_r, dest_g, dest_b, dest_a;
- uint16_t dat;
- int sel;
- int32_t new_depth, w_depth;
-
- if (state->w & 0xffff00000000)
- w_depth = 0;
- else if (!(state->w & 0xffff0000))
- w_depth = 0xf001;
- else
- {
- int exp = voodoo_fls((uint16_t)((uint32_t)state->w >> 16));
- int mant = ((~(uint32_t)state->w >> (19 - exp))) & 0xfff;
- w_depth = (exp << 12) + mant + 1;
- if (w_depth > 0xffff)
- w_depth = 0xffff;
- }
-
-// w_depth = CLAMP16(w_depth);
-
- if (params->fbzMode & FBZ_W_BUFFER)
- new_depth = w_depth;
- else
- new_depth = CLAMP16(state->z >> 12);
-
- if (params->fbzMode & FBZ_DEPTH_BIAS)
- new_depth = CLAMP16(new_depth + (int16_t)params->zaColor);
-
- if (params->fbzMode & FBZ_DEPTH_ENABLE)
- {
- uint16_t old_depth = aux_mem[x];
-
- DEPTH_TEST((params->fbzMode & FBZ_DEPTH_SOURCE) ? (params->zaColor & 0xffff) : new_depth);
- }
-
- dat = fb_mem[x];
- dest_r = (dat >> 8) & 0xf8;
- dest_g = (dat >> 3) & 0xfc;
- dest_b = (dat << 3) & 0xf8;
- dest_r |= (dest_r >> 5);
- dest_g |= (dest_g >> 6);
- dest_b |= (dest_b >> 5);
- dest_a = 0xff;
-
- if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED)
- {
- if ((params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL || !voodoo->dual_tmus)
- {
- /*TMU0 only sampling local colour or only one TMU, only sample TMU0*/
- voodoo_tmu_fetch(voodoo, params, state, 0, x);
- }
- else if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH)
- {
- /*TMU0 in pass-through mode, only sample TMU1*/
- voodoo_tmu_fetch(voodoo, params, state, 1, x);
-
- state->tex_r[0] = state->tex_r[1];
- state->tex_g[0] = state->tex_g[1];
- state->tex_b[0] = state->tex_b[1];
- state->tex_a[0] = state->tex_a[1];
- }
- else
- {
- voodoo_tmu_fetch_and_blend(voodoo, params, state, x);
- }
-
- if ((params->fbzMode & FBZ_CHROMAKEY) &&
- state->tex_r[0] == params->chromaKey_r &&
- state->tex_g[0] == params->chromaKey_g &&
- state->tex_b[0] == params->chromaKey_b)
- {
- voodoo->fbiChromaFail++;
- goto skip_pixel;
- }
- }
-
- if (voodoo->trexInit1[0] & (1 << 18))
- {
- state->tex_r[0] = state->tex_g[0] = 0;
- state->tex_b[0] = voodoo->tmuConfig;
- }
-
- if (cc_localselect_override)
- sel = (state->tex_a[0] & 0x80) ? 1 : 0;
- else
- sel = cc_localselect;
-
- if (sel)
- {
- clocal_r = (params->color0 >> 16) & 0xff;
- clocal_g = (params->color0 >> 8) & 0xff;
- clocal_b = params->color0 & 0xff;
- }
- else
- {
- clocal_r = CLAMP(state->ir >> 12);
- clocal_g = CLAMP(state->ig >> 12);
- clocal_b = CLAMP(state->ib >> 12);
- }
-
- switch (_rgb_sel)
- {
- case CC_LOCALSELECT_ITER_RGB: /*Iterated RGB*/
- cother_r = CLAMP(state->ir >> 12);
- cother_g = CLAMP(state->ig >> 12);
- cother_b = CLAMP(state->ib >> 12);
- break;
-
- case CC_LOCALSELECT_TEX: /*TREX Color Output*/
- cother_r = state->tex_r[0];
- cother_g = state->tex_g[0];
- cother_b = state->tex_b[0];
- break;
-
- case CC_LOCALSELECT_COLOR1: /*Color1 RGB*/
- cother_r = (params->color1 >> 16) & 0xff;
- cother_g = (params->color1 >> 8) & 0xff;
- cother_b = params->color1 & 0xff;
- break;
-
- case CC_LOCALSELECT_LFB: /*Linear Frame Buffer*/
- cother_r = src_r;
- cother_g = src_g;
- cother_b = src_b;
- break;
- }
-
- switch (cca_localselect)
- {
- case CCA_LOCALSELECT_ITER_A:
- alocal = CLAMP(state->ia >> 12);
- break;
-
- case CCA_LOCALSELECT_COLOR0:
- alocal = (params->color0 >> 24) & 0xff;
- break;
-
- case CCA_LOCALSELECT_ITER_Z:
- alocal = CLAMP(state->z >> 20);
- break;
-
- default:
- fatal("Bad cca_localselect %i\n", cca_localselect);
- alocal = 0xff;
- break;
- }
-
- switch (a_sel)
- {
- case A_SEL_ITER_A:
- aother = CLAMP(state->ia >> 12);
- break;
- case A_SEL_TEX:
- aother = state->tex_a[0];
- break;
- case A_SEL_COLOR1:
- aother = (params->color1 >> 24) & 0xff;
- break;
- default:
- fatal("Bad a_sel %i\n", a_sel);
- aother = 0;
- break;
- }
-
- if (cc_zero_other)
- {
- src_r = 0;
- src_g = 0;
- src_b = 0;
- }
- else
- {
- src_r = cother_r;
- src_g = cother_g;
- src_b = cother_b;
- }
-
- if (cca_zero_other)
- src_a = 0;
- else
- src_a = aother;
-
- if (cc_sub_clocal)
- {
- src_r -= clocal_r;
- src_g -= clocal_g;
- src_b -= clocal_b;
- }
-
- if (cca_sub_clocal)
- src_a -= alocal;
-
- switch (cc_mselect)
- {
- case CC_MSELECT_ZERO:
- msel_r = 0;
- msel_g = 0;
- msel_b = 0;
- break;
- case CC_MSELECT_CLOCAL:
- msel_r = clocal_r;
- msel_g = clocal_g;
- msel_b = clocal_b;
- break;
- case CC_MSELECT_AOTHER:
- msel_r = aother;
- msel_g = aother;
- msel_b = aother;
- break;
- case CC_MSELECT_ALOCAL:
- msel_r = alocal;
- msel_g = alocal;
- msel_b = alocal;
- break;
- case CC_MSELECT_TEX:
- msel_r = state->tex_a[0];
- msel_g = state->tex_a[0];
- msel_b = state->tex_a[0];
- break;
- case CC_MSELECT_TEXRGB:
- msel_r = state->tex_r[0];
- msel_g = state->tex_g[0];
- msel_b = state->tex_b[0];
- break;
-
- default:
- fatal("Bad cc_mselect %i\n", cc_mselect);
- msel_r = 0;
- msel_g = 0;
- msel_b = 0;
- break;
- }
-
- switch (cca_mselect)
- {
- case CCA_MSELECT_ZERO:
- msel_a = 0;
- break;
- case CCA_MSELECT_ALOCAL:
- msel_a = alocal;
- break;
- case CCA_MSELECT_AOTHER:
- msel_a = aother;
- break;
- case CCA_MSELECT_ALOCAL2:
- msel_a = alocal;
- break;
- case CCA_MSELECT_TEX:
- msel_a = state->tex_a[0];
- break;
-
- default:
- fatal("Bad cca_mselect %i\n", cca_mselect);
- msel_a = 0;
- break;
- }
-
- if (!cc_reverse_blend)
- {
- msel_r ^= 0xff;
- msel_g ^= 0xff;
- msel_b ^= 0xff;
- }
- msel_r++;
- msel_g++;
- msel_b++;
-
- if (!cca_reverse_blend)
- msel_a ^= 0xff;
- msel_a++;
-
- src_r = (src_r * msel_r) >> 8;
- src_g = (src_g * msel_g) >> 8;
- src_b = (src_b * msel_b) >> 8;
- src_a = (src_a * msel_a) >> 8;
-
- switch (cc_add)
- {
- case CC_ADD_CLOCAL:
- src_r += clocal_r;
- src_g += clocal_g;
- src_b += clocal_b;
- break;
- case CC_ADD_ALOCAL:
- src_r += alocal;
- src_g += alocal;
- src_b += alocal;
- break;
- case 0:
- break;
- default:
- fatal("Bad cc_add %i\n", cc_add);
- }
-
- if (cca_add)
- src_a += alocal;
-
- src_r = CLAMP(src_r);
- src_g = CLAMP(src_g);
- src_b = CLAMP(src_b);
- src_a = CLAMP(src_a);
-
- if (cc_invert_output)
- {
- src_r ^= 0xff;
- src_g ^= 0xff;
- src_b ^= 0xff;
- }
- if (cca_invert_output)
- src_a ^= 0xff;
-
- if (params->fogMode & FOG_ENABLE)
- APPLY_FOG(src_r, src_g, src_b, state->z, state->ia, state->w);
-
- if (params->alphaMode & 1)
- ALPHA_TEST(src_a);
-
- if (params->alphaMode & (1 << 4))
- ALPHA_BLEND(src_r, src_g, src_b, src_a);
-
- if (update)
- {
- if (dither)
- {
- if (dither2x2)
- {
- src_r = dither_rb2x2[src_r][real_y & 1][x & 1];
- src_g = dither_g2x2[src_g][real_y & 1][x & 1];
- src_b = dither_rb2x2[src_b][real_y & 1][x & 1];
- }
- else
- {
- src_r = dither_rb[src_r][real_y & 3][x & 3];
- src_g = dither_g[src_g][real_y & 3][x & 3];
- src_b = dither_rb[src_b][real_y & 3][x & 3];
- }
- }
- else
- {
- src_r >>= 3;
- src_g >>= 2;
- src_b >>= 3;
- }
-
- if (params->fbzMode & FBZ_RGB_WMASK)
- fb_mem[x] = src_b | (src_g << 5) | (src_r << 11);
-
- if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE))
- aux_mem[x] = new_depth;
- }
- }
- voodoo_output &= ~2;
- voodoo->fbiPixelsOut++;
-skip_pixel:
- if (state->xdir > 0)
- {
- state->ir += params->dRdX;
- state->ig += params->dGdX;
- state->ib += params->dBdX;
- state->ia += params->dAdX;
- state->z += params->dZdX;
- state->tmu0_s += params->tmu[0].dSdX;
- state->tmu0_t += params->tmu[0].dTdX;
- state->tmu0_w += params->tmu[0].dWdX;
- state->tmu1_s += params->tmu[1].dSdX;
- state->tmu1_t += params->tmu[1].dTdX;
- state->tmu1_w += params->tmu[1].dWdX;
- state->w += params->dWdX;
- }
- else
- {
- state->ir -= params->dRdX;
- state->ig -= params->dGdX;
- state->ib -= params->dBdX;
- state->ia -= params->dAdX;
- state->z -= params->dZdX;
- state->tmu0_s -= params->tmu[0].dSdX;
- state->tmu0_t -= params->tmu[0].dTdX;
- state->tmu0_w -= params->tmu[0].dWdX;
- state->tmu1_s -= params->tmu[1].dSdX;
- state->tmu1_t -= params->tmu[1].dTdX;
- state->tmu1_w -= params->tmu[1].dWdX;
- state->w -= params->dWdX;
- }
-
- x += state->xdir;
- } while (start_x != x2);
-
- voodoo->pixel_count[odd_even] += state->pixel_count;
- voodoo->texel_count[odd_even] += state->texel_count;
- voodoo->fbiPixelsIn += state->pixel_count;
-
- if (voodoo->params.draw_offset == voodoo->params.front_offset)
- voodoo->dirty_line[real_y >> 1] = 1;
-next_line:
- if (SLI_ENABLED)
- {
- state->base_r += params->dRdY;
- state->base_g += params->dGdY;
- state->base_b += params->dBdY;
- state->base_a += params->dAdY;
- state->base_z += params->dZdY;
- state->tmu[0].base_s += params->tmu[0].dSdY;
- state->tmu[0].base_t += params->tmu[0].dTdY;
- state->tmu[0].base_w += params->tmu[0].dWdY;
- state->tmu[1].base_s += params->tmu[1].dSdY;
- state->tmu[1].base_t += params->tmu[1].dTdY;
- state->tmu[1].base_w += params->tmu[1].dWdY;
- state->base_w += params->dWdY;
- state->xstart += state->dx1;
- state->xend += state->dx2;
- }
- state->base_r += params->dRdY;
- state->base_g += params->dGdY;
- state->base_b += params->dBdY;
- state->base_a += params->dAdY;
- state->base_z += params->dZdY;
- state->tmu[0].base_s += params->tmu[0].dSdY;
- state->tmu[0].base_t += params->tmu[0].dTdY;
- state->tmu[0].base_w += params->tmu[0].dWdY;
- state->tmu[1].base_s += params->tmu[1].dSdY;
- state->tmu[1].base_t += params->tmu[1].dTdY;
- state->tmu[1].base_w += params->tmu[1].dWdY;
- state->base_w += params->dWdY;
- state->xstart += state->dx1;
- state->xend += state->dx2;
- }
-
- voodoo->texture_cache[0][params->tex_entry[0]].refcount_r[odd_even]++;
- voodoo->texture_cache[1][params->tex_entry[1]].refcount_r[odd_even]++;
-}
-
-static void voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params, int odd_even)
-{
- voodoo_state_t state;
- int vertexAy_adjusted;
- int vertexCy_adjusted;
- int dx, dy;
-
- uint64_t tempdx, tempdy;
- uint64_t tempLOD;
- int LOD;
- int lodbias;
-
- voodoo->tri_count++;
-
- dx = 8 - (params->vertexAx & 0xf);
- if ((params->vertexAx & 0xf) > 8)
- dx += 16;
- dy = 8 - (params->vertexAy & 0xf);
- if ((params->vertexAy & 0xf) > 8)
- dy += 16;
-
-/* pclog("voodoo_triangle %i %i %i : vA %f, %f vB %f, %f vC %f, %f f %i,%i %08x %08x %08x,%08x tex=%i,%i fogMode=%08x\n", odd_even, voodoo->params_read_idx[odd_even], voodoo->params_read_idx[odd_even] & PARAM_MASK, (float)params->vertexAx / 16.0, (float)params->vertexAy / 16.0,
- (float)params->vertexBx / 16.0, (float)params->vertexBy / 16.0,
- (float)params->vertexCx / 16.0, (float)params->vertexCy / 16.0,
- (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[0] : 0,
- (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[1] : 0, params->fbzColorPath, params->alphaMode, params->textureMode[0],params->textureMode[1], params->tex_entry[0],params->tex_entry[1], params->fogMode);*/
-
- state.base_r = params->startR;
- state.base_g = params->startG;
- state.base_b = params->startB;
- state.base_a = params->startA;
- state.base_z = params->startZ;
- state.tmu[0].base_s = params->tmu[0].startS;
- state.tmu[0].base_t = params->tmu[0].startT;
- state.tmu[0].base_w = params->tmu[0].startW;
- state.tmu[1].base_s = params->tmu[1].startS;
- state.tmu[1].base_t = params->tmu[1].startT;
- state.tmu[1].base_w = params->tmu[1].startW;
- state.base_w = params->startW;
-
- if (params->fbzColorPath & FBZ_PARAM_ADJUST)
- {
- state.base_r += (dx*params->dRdX + dy*params->dRdY) >> 4;
- state.base_g += (dx*params->dGdX + dy*params->dGdY) >> 4;
- state.base_b += (dx*params->dBdX + dy*params->dBdY) >> 4;
- state.base_a += (dx*params->dAdX + dy*params->dAdY) >> 4;
- state.base_z += (dx*params->dZdX + dy*params->dZdY) >> 4;
- state.tmu[0].base_s += (dx*params->tmu[0].dSdX + dy*params->tmu[0].dSdY) >> 4;
- state.tmu[0].base_t += (dx*params->tmu[0].dTdX + dy*params->tmu[0].dTdY) >> 4;
- state.tmu[0].base_w += (dx*params->tmu[0].dWdX + dy*params->tmu[0].dWdY) >> 4;
- state.tmu[1].base_s += (dx*params->tmu[1].dSdX + dy*params->tmu[1].dSdY) >> 4;
- state.tmu[1].base_t += (dx*params->tmu[1].dTdX + dy*params->tmu[1].dTdY) >> 4;
- state.tmu[1].base_w += (dx*params->tmu[1].dWdX + dy*params->tmu[1].dWdY) >> 4;
- state.base_w += (dx*params->dWdX + dy*params->dWdY) >> 4;
- }
-
- tris++;
-
- state.vertexAy = params->vertexAy & ~0xffff0000;
- if (state.vertexAy & 0x8000)
- state.vertexAy |= 0xffff0000;
- state.vertexBy = params->vertexBy & ~0xffff0000;
- if (state.vertexBy & 0x8000)
- state.vertexBy |= 0xffff0000;
- state.vertexCy = params->vertexCy & ~0xffff0000;
- if (state.vertexCy & 0x8000)
- state.vertexCy |= 0xffff0000;
-
- state.vertexAx = params->vertexAx & ~0xffff0000;
- if (state.vertexAx & 0x8000)
- state.vertexAx |= 0xffff0000;
- state.vertexBx = params->vertexBx & ~0xffff0000;
- if (state.vertexBx & 0x8000)
- state.vertexBx |= 0xffff0000;
- state.vertexCx = params->vertexCx & ~0xffff0000;
- if (state.vertexCx & 0x8000)
- state.vertexCx |= 0xffff0000;
-
- vertexAy_adjusted = (state.vertexAy+7) >> 4;
- vertexCy_adjusted = (state.vertexCy+7) >> 4;
-
- if (state.vertexBy - state.vertexAy)
- state.dxAB = (int)((((int64_t)state.vertexBx << 12) - ((int64_t)state.vertexAx << 12)) << 4) / (int)(state.vertexBy - state.vertexAy);
- else
- state.dxAB = 0;
- if (state.vertexCy - state.vertexAy)
- state.dxAC = (int)((((int64_t)state.vertexCx << 12) - ((int64_t)state.vertexAx << 12)) << 4) / (int)(state.vertexCy - state.vertexAy);
- else
- state.dxAC = 0;
- if (state.vertexCy - state.vertexBy)
- state.dxBC = (int)((((int64_t)state.vertexCx << 12) - ((int64_t)state.vertexBx << 12)) << 4) / (int)(state.vertexCy - state.vertexBy);
- else
- state.dxBC = 0;
-
- state.lod_min[0] = (params->tLOD[0] & 0x3f) << 6;
- state.lod_max[0] = ((params->tLOD[0] >> 6) & 0x3f) << 6;
- if (state.lod_max[0] > 0x800)
- state.lod_max[0] = 0x800;
- state.lod_min[1] = (params->tLOD[1] & 0x3f) << 6;
- state.lod_max[1] = ((params->tLOD[1] >> 6) & 0x3f) << 6;
- if (state.lod_max[1] > 0x800)
- state.lod_max[1] = 0x800;
-
- state.xstart = state.xend = state.vertexAx << 8;
- state.xdir = params->sign ? -1 : 1;
-
- state.y = (state.vertexAy + 8) >> 4;
- state.ydir = 1;
-
-
- tempdx = (params->tmu[0].dSdX >> 14) * (params->tmu[0].dSdX >> 14) + (params->tmu[0].dTdX >> 14) * (params->tmu[0].dTdX >> 14);
- tempdy = (params->tmu[0].dSdY >> 14) * (params->tmu[0].dSdY >> 14) + (params->tmu[0].dTdY >> 14) * (params->tmu[0].dTdY >> 14);
-
- if (tempdx > tempdy)
- tempLOD = tempdx;
- else
- tempLOD = tempdy;
-
- LOD = (int)(log2((double)tempLOD / (double)(1ULL << 36)) * 256);
- LOD >>= 2;
-
- lodbias = (params->tLOD[0] >> 12) & 0x3f;
- if (lodbias & 0x20)
- lodbias |= ~0x3f;
- state.tmu[0].lod = LOD + (lodbias << 6);
-
-
- tempdx = (params->tmu[1].dSdX >> 14) * (params->tmu[1].dSdX >> 14) + (params->tmu[1].dTdX >> 14) * (params->tmu[1].dTdX >> 14);
- tempdy = (params->tmu[1].dSdY >> 14) * (params->tmu[1].dSdY >> 14) + (params->tmu[1].dTdY >> 14) * (params->tmu[1].dTdY >> 14);
-
- if (tempdx > tempdy)
- tempLOD = tempdx;
- else
- tempLOD = tempdy;
-
- LOD = (int)(log2((double)tempLOD / (double)(1ULL << 36)) * 256);
- LOD >>= 2;
-
- lodbias = (params->tLOD[1] >> 12) & 0x3f;
- if (lodbias & 0x20)
- lodbias |= ~0x3f;
- state.tmu[1].lod = LOD + (lodbias << 6);
-
-
- voodoo_half_triangle(voodoo, params, &state, vertexAy_adjusted, vertexCy_adjusted, odd_even);
-}
-
-static inline void wake_render_thread(voodoo_t *voodoo)
-{
- thread_set_event(voodoo->wake_render_thread[0]); /*Wake up render thread if moving from idle*/
- if (voodoo->render_threads == 2)
- thread_set_event(voodoo->wake_render_thread[1]); /*Wake up render thread if moving from idle*/
-}
-
-static inline void wait_for_render_thread_idle(voodoo_t *voodoo)
-{
- while (!PARAM_EMPTY_1 || (voodoo->render_threads == 2 && !PARAM_EMPTY_2) || voodoo->render_voodoo_busy[0] || (voodoo->render_threads == 2 && voodoo->render_voodoo_busy[1]))
- {
- wake_render_thread(voodoo);
- if (!PARAM_EMPTY_1 || voodoo->render_voodoo_busy[0])
- thread_wait_event(voodoo->render_not_full_event[0], 1);
- if (voodoo->render_threads == 2 && (!PARAM_EMPTY_2 || voodoo->render_voodoo_busy[1]))
- thread_wait_event(voodoo->render_not_full_event[1], 1);
- }
-}
-
-static void render_thread(void *param, int odd_even)
-{
- voodoo_t *voodoo = (voodoo_t *)param;
-
- while (1)
- {
- thread_set_event(voodoo->render_not_full_event[odd_even]);
- thread_wait_event(voodoo->wake_render_thread[odd_even], -1);
- thread_reset_event(voodoo->wake_render_thread[odd_even]);
- voodoo->render_voodoo_busy[odd_even] = 1;
-
- while (!(odd_even ? PARAM_EMPTY_2 : PARAM_EMPTY_1))
- {
- uint64_t start_time = timer_read();
- uint64_t end_time;
- voodoo_params_t *params = &voodoo->params_buffer[voodoo->params_read_idx[odd_even] & PARAM_MASK];
-
- voodoo_triangle(voodoo, params, odd_even);
-
- voodoo->params_read_idx[odd_even]++;
-
- if ((odd_even ? PARAM_ENTRIES_2 : PARAM_ENTRIES_1) > (PARAM_SIZE - 10))
- thread_set_event(voodoo->render_not_full_event[odd_even]);
-
- end_time = timer_read();
- voodoo->render_time[odd_even] += end_time - start_time;
- }
-
- voodoo->render_voodoo_busy[odd_even] = 0;
- }
-}
-
-static void render_thread_1(void *param)
-{
- render_thread(param, 0);
-}
-static void render_thread_2(void *param)
-{
- render_thread(param, 1);
-}
-
-static inline void queue_triangle(voodoo_t *voodoo, voodoo_params_t *params)
-{
- voodoo_params_t *params_new = &voodoo->params_buffer[voodoo->params_write_idx & PARAM_MASK];
-
- while (PARAM_FULL_1 || (voodoo->render_threads == 2 && PARAM_FULL_2))
- {
- thread_reset_event(voodoo->render_not_full_event[0]);
- if (voodoo->render_threads == 2)
- thread_reset_event(voodoo->render_not_full_event[1]);
- if (PARAM_FULL_1)
- {
- thread_wait_event(voodoo->render_not_full_event[0], -1); /*Wait for room in ringbuffer*/
- }
- if (voodoo->render_threads == 2 && PARAM_FULL_2)
- {
- thread_wait_event(voodoo->render_not_full_event[1], -1); /*Wait for room in ringbuffer*/
- }
- }
-
- use_texture(voodoo, params, 0);
- if (voodoo->dual_tmus)
- use_texture(voodoo, params, 1);
-
- memcpy(params_new, params, sizeof(voodoo_params_t));
-
- voodoo->params_write_idx++;
-
- if (PARAM_ENTRIES_1 < 4 || (voodoo->render_threads == 2 && PARAM_ENTRIES_2 < 4))
- wake_render_thread(voodoo);
-}
-
-static void voodoo_fastfill(voodoo_t *voodoo, voodoo_params_t *params)
-{
- int y;
- int low_y, high_y;
-
- if (params->fbzMode & (1 << 17))
- {
- high_y = voodoo->v_disp - params->clipLowY;
- low_y = voodoo->v_disp - params->clipHighY;
- }
- else
- {
- low_y = params->clipLowY;
- high_y = params->clipHighY;
- }
-
- if (params->fbzMode & FBZ_RGB_WMASK)
- {
- int r, g, b;
- uint16_t col;
-
- r = ((params->color1 >> 16) >> 3) & 0x1f;
- g = ((params->color1 >> 8) >> 2) & 0x3f;
- b = (params->color1 >> 3) & 0x1f;
- col = b | (g << 5) | (r << 11);
-
- if (SLI_ENABLED)
- {
- for (y = low_y; y < high_y; y += 2)
- {
- uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask];
- int x;
-
- for (x = params->clipLeft; x < params->clipRight; x++)
- cbuf[x] = col;
- }
- }
- else
- {
- for (y = low_y; y < high_y; y++)
- {
- uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + y*voodoo->row_width) & voodoo->fb_mask];
- int x;
-
- for (x = params->clipLeft; x < params->clipRight; x++)
- cbuf[x] = col;
- }
- }
- }
- if (params->fbzMode & FBZ_DEPTH_WMASK)
- {
- if (SLI_ENABLED)
- {
- for (y = low_y; y < high_y; y += 2)
- {
- uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask];
- int x;
-
- for (x = params->clipLeft; x < params->clipRight; x++)
- abuf[x] = params->zaColor & 0xffff;
- }
- }
- else
- {
- for (y = low_y; y < high_y; y++)
- {
- uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + y*voodoo->row_width) & voodoo->fb_mask];
- int x;
-
- for (x = params->clipLeft; x < params->clipRight; x++)
- abuf[x] = params->zaColor & 0xffff;
- }
- }
- }
-}
-
-enum
-{
- SETUPMODE_RGB = (1 << 0),
- SETUPMODE_ALPHA = (1 << 1),
- SETUPMODE_Z = (1 << 2),
- SETUPMODE_Wb = (1 << 3),
- SETUPMODE_W0 = (1 << 4),
- SETUPMODE_S0_T0 = (1 << 5),
- SETUPMODE_W1 = (1 << 6),
- SETUPMODE_S1_T1 = (1 << 7),
-
- SETUPMODE_STRIP_MODE = (1 << 16),
- SETUPMODE_CULLING_ENABLE = (1 << 17),
- SETUPMODE_CULLING_SIGN = (1 << 18),
- SETUPMODE_DISABLE_PINGPONG = (1 << 19)
-};
-
-static void triangle_setup(voodoo_t *voodoo)
-{
- float dxAB, dxBC, dyAB, dyBC;
- float area;
- int va = 0, vb = 1, vc = 2;
- int reverse_cull = 0;
- vert_t verts[3];
-
- verts[0] = voodoo->verts[0];
- verts[1] = voodoo->verts[1];
- verts[2] = voodoo->verts[2];
-
- if (verts[0].sVy < verts[1].sVy)
- {
- if (verts[1].sVy < verts[2].sVy)
- {
- /* V1>V0, V2>V1, V2>V1>V0*/
- va = 0; /*OK*/
- vb = 1;
- vc = 2;
- }
- else
- {
- /* V1>V0, V1>V2*/
- if (verts[0].sVy < verts[2].sVy)
- {
- /* V1>V0, V1>V2, V2>V0, V1>V2>V0*/
- va = 0;
- vb = 2;
- vc = 1;
- reverse_cull = 1;
- }
- else
- {
- /* V1>V0, V1>V2, V0>V2, V1>V0>V2*/
- va = 2;
- vb = 0;
- vc = 1;
- }
- }
- }
- else
- {
- if (verts[1].sVy < verts[2].sVy)
- {
- /* V0>V1, V2>V1*/
- if (verts[0].sVy < verts[2].sVy)
- {
- /* V0>V1, V2>V1, V2>V0, V2>V0>V1*/
- va = 1;
- vb = 0;
- vc = 2;
- reverse_cull = 1;
- }
- else
- {
- /* V0>V1, V2>V1, V0>V2, V0>V2>V1*/
- va = 1;
- vb = 2;
- vc = 0;
- }
- }
- else
- {
- /*V0>V1>V2*/
- va = 2;
- vb = 1;
- vc = 0;
- reverse_cull = 1;
- }
- }
-
- dxAB = verts[va].sVx - verts[vb].sVx;
- dxBC = verts[vb].sVx - verts[vc].sVx;
- dyAB = verts[va].sVy - verts[vb].sVy;
- dyBC = verts[vb].sVy - verts[vc].sVy;
-
- area = dxAB * dyBC - dxBC * dyAB;
-
- if (area == 0.0)
- {
- if ((voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE) &&
- !(voodoo->sSetupMode & SETUPMODE_DISABLE_PINGPONG))
- voodoo->sSetupMode ^= SETUPMODE_CULLING_SIGN;
-
- return;
- }
-
- dxAB /= area;
- dxBC /= area;
- dyAB /= area;
- dyBC /= area;
-
- if (voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE)
- {
- int cull_sign = voodoo->sSetupMode & SETUPMODE_CULLING_SIGN;
- int sign = (area < 0.0);
-
- if (!(voodoo->sSetupMode & SETUPMODE_DISABLE_PINGPONG))
- voodoo->sSetupMode ^= SETUPMODE_CULLING_SIGN;
-
- if (reverse_cull)
- sign = !sign;
-
- if (cull_sign && sign)
- return;
- if (!cull_sign && !sign)
- return;
- }
-
- voodoo->params.vertexAx = (int32_t)(int16_t)((int32_t)(verts[va].sVx * 16.0f) & 0xffff);
- voodoo->params.vertexAy = (int32_t)(int16_t)((int32_t)(verts[va].sVy * 16.0f) & 0xffff);
- voodoo->params.vertexBx = (int32_t)(int16_t)((int32_t)(verts[vb].sVx * 16.0f) & 0xffff);
- voodoo->params.vertexBy = (int32_t)(int16_t)((int32_t)(verts[vb].sVy * 16.0f) & 0xffff);
- voodoo->params.vertexCx = (int32_t)(int16_t)((int32_t)(verts[vc].sVx * 16.0f) & 0xffff);
- voodoo->params.vertexCy = (int32_t)(int16_t)((int32_t)(verts[vc].sVy * 16.0f) & 0xffff);
-
- if (voodoo->params.vertexAy > voodoo->params.vertexBy || voodoo->params.vertexBy > voodoo->params.vertexCy)
- fatal("triangle_setup wrong order %d %d %d\n", voodoo->params.vertexAy, voodoo->params.vertexBy, voodoo->params.vertexCy);
-
- if (voodoo->sSetupMode & SETUPMODE_RGB)
- {
- voodoo->params.startR = (int32_t)(verts[va].sRed * 4096.0f);
- voodoo->params.dRdX = (int32_t)(((verts[va].sRed - verts[vb].sRed) * dyBC - (verts[vb].sRed - verts[vc].sRed) * dyAB) * 4096.0f);
- voodoo->params.dRdY = (int32_t)(((verts[vb].sRed - verts[vc].sRed) * dxAB - (verts[va].sRed - verts[vb].sRed) * dxBC) * 4096.0f);
- voodoo->params.startG = (int32_t)(verts[va].sGreen * 4096.0f);
- voodoo->params.dGdX = (int32_t)(((verts[va].sGreen - verts[vb].sGreen) * dyBC - (verts[vb].sGreen - verts[vc].sGreen) * dyAB) * 4096.0f);
- voodoo->params.dGdY = (int32_t)(((verts[vb].sGreen - verts[vc].sGreen) * dxAB - (verts[va].sGreen - verts[vb].sGreen) * dxBC) * 4096.0f);
- voodoo->params.startB = (int32_t)(verts[va].sBlue * 4096.0f);
- voodoo->params.dBdX = (int32_t)(((verts[va].sBlue - verts[vb].sBlue) * dyBC - (verts[vb].sBlue - verts[vc].sBlue) * dyAB) * 4096.0f);
- voodoo->params.dBdY = (int32_t)(((verts[vb].sBlue - verts[vc].sBlue) * dxAB - (verts[va].sBlue - verts[vb].sBlue) * dxBC) * 4096.0f);
- }
- if (voodoo->sSetupMode & SETUPMODE_ALPHA)
- {
- voodoo->params.startA = (int32_t)(verts[va].sAlpha * 4096.0f);
- voodoo->params.dAdX = (int32_t)(((verts[va].sAlpha - verts[vb].sAlpha) * dyBC - (verts[vb].sAlpha - verts[vc].sAlpha) * dyAB) * 4096.0f);
- voodoo->params.dAdY = (int32_t)(((verts[vb].sAlpha - verts[vc].sAlpha) * dxAB - (verts[va].sAlpha - verts[vb].sAlpha) * dxBC) * 4096.0f);
- }
- if (voodoo->sSetupMode & SETUPMODE_Z)
- {
- voodoo->params.startZ = (int32_t)(verts[va].sVz * 4096.0f);
- voodoo->params.dZdX = (int32_t)(((verts[va].sVz - verts[vb].sVz) * dyBC - (verts[vb].sVz - verts[vc].sVz) * dyAB) * 4096.0f);
- voodoo->params.dZdY = (int32_t)(((verts[vb].sVz - verts[vc].sVz) * dxAB - (verts[va].sVz - verts[vb].sVz) * dxBC) * 4096.0f);
- }
- if (voodoo->sSetupMode & SETUPMODE_Wb)
- {
- voodoo->params.startW = (int64_t)(verts[va].sWb * 4294967296.0f);
- voodoo->params.dWdX = (int64_t)(((verts[va].sWb - verts[vb].sWb) * dyBC - (verts[vb].sWb - verts[vc].sWb) * dyAB) * 4294967296.0f);
- voodoo->params.dWdY = (int64_t)(((verts[vb].sWb - verts[vc].sWb) * dxAB - (verts[va].sWb - verts[vb].sWb) * dxBC) * 4294967296.0f);
- voodoo->params.tmu[0].startW = voodoo->params.tmu[1].startW = voodoo->params.startW;
- voodoo->params.tmu[0].dWdX = voodoo->params.tmu[1].dWdX = voodoo->params.dWdX;
- voodoo->params.tmu[0].dWdY = voodoo->params.tmu[1].dWdY = voodoo->params.dWdY;
- }
- if (voodoo->sSetupMode & SETUPMODE_W0)
- {
- voodoo->params.tmu[0].startW = (int64_t)(verts[va].sW0 * 4294967296.0f);
- voodoo->params.tmu[0].dWdX = (int64_t)(((verts[va].sW0 - verts[vb].sW0) * dyBC - (verts[vb].sW0 - verts[vc].sW0) * dyAB) * 4294967296.0f);
- voodoo->params.tmu[0].dWdY = (int64_t)(((verts[vb].sW0 - verts[vc].sW0) * dxAB - (verts[va].sW0 - verts[vb].sW0) * dxBC) * 4294967296.0f);
- voodoo->params.tmu[1].startW = voodoo->params.tmu[0].startW;
- voodoo->params.tmu[1].dWdX = voodoo->params.tmu[0].dWdX;
- voodoo->params.tmu[1].dWdY = voodoo->params.tmu[0].dWdY;
- }
- if (voodoo->sSetupMode & SETUPMODE_S0_T0)
- {
- voodoo->params.tmu[0].startS = (int64_t)(verts[va].sS0 * 4294967296.0f);
- voodoo->params.tmu[0].dSdX = (int64_t)(((verts[va].sS0 - verts[vb].sS0) * dyBC - (verts[vb].sS0 - verts[vc].sS0) * dyAB) * 4294967296.0f);
- voodoo->params.tmu[0].dSdY = (int64_t)(((verts[vb].sS0 - verts[vc].sS0) * dxAB - (verts[va].sS0 - verts[vb].sS0) * dxBC) * 4294967296.0f);
- voodoo->params.tmu[0].startT = (int64_t)(verts[va].sT0 * 4294967296.0f);
- voodoo->params.tmu[0].dTdX = (int64_t)(((verts[va].sT0 - verts[vb].sT0) * dyBC - (verts[vb].sT0 - verts[vc].sT0) * dyAB) * 4294967296.0f);
- voodoo->params.tmu[0].dTdY = (int64_t)(((verts[vb].sT0 - verts[vc].sT0) * dxAB - (verts[va].sT0 - verts[vb].sT0) * dxBC) * 4294967296.0f);
- voodoo->params.tmu[1].startS = voodoo->params.tmu[0].startS;
- voodoo->params.tmu[1].dSdX = voodoo->params.tmu[0].dSdX;
- voodoo->params.tmu[1].dSdY = voodoo->params.tmu[0].dSdY;
- voodoo->params.tmu[1].startT = voodoo->params.tmu[0].startT;
- voodoo->params.tmu[1].dTdX = voodoo->params.tmu[0].dTdX;
- voodoo->params.tmu[1].dTdY = voodoo->params.tmu[0].dTdY;
- }
- if (voodoo->sSetupMode & SETUPMODE_W1)
- {
- voodoo->params.tmu[1].startW = (int64_t)(verts[va].sW1 * 4294967296.0f);
- voodoo->params.tmu[1].dWdX = (int64_t)(((verts[va].sW1 - verts[vb].sW1) * dyBC - (verts[vb].sW1 - verts[vc].sW1) * dyAB) * 4294967296.0f);
- voodoo->params.tmu[1].dWdY = (int64_t)(((verts[vb].sW1 - verts[vc].sW1) * dxAB - (verts[va].sW1 - verts[vb].sW1) * dxBC) * 4294967296.0f);
- }
- if (voodoo->sSetupMode & SETUPMODE_S1_T1)
- {
- voodoo->params.tmu[1].startS = (int64_t)(verts[va].sS1 * 4294967296.0f);
- voodoo->params.tmu[1].dSdX = (int64_t)(((verts[va].sS1 - verts[vb].sS1) * dyBC - (verts[vb].sS1 - verts[vc].sS1) * dyAB) * 4294967296.0f);
- voodoo->params.tmu[1].dSdY = (int64_t)(((verts[vb].sS1 - verts[vc].sS1) * dxAB - (verts[va].sS1 - verts[vb].sS1) * dxBC) * 4294967296.0f);
- voodoo->params.tmu[1].startT = (int64_t)(verts[va].sT1 * 4294967296.0f);
- voodoo->params.tmu[1].dTdX = (int64_t)(((verts[va].sT1 - verts[vb].sT1) * dyBC - (verts[vb].sT1 - verts[vc].sT1) * dyAB) * 4294967296.0f);
- voodoo->params.tmu[1].dTdY = (int64_t)(((verts[vb].sT1 - verts[vc].sT1) * dxAB - (verts[va].sT1 - verts[vb].sT1) * dxBC) * 4294967296.0f);
- }
-
- voodoo->params.sign = (area < 0.0);
-
- if (voodoo->ncc_dirty[0])
- voodoo_update_ncc(voodoo, 0);
- if (voodoo->ncc_dirty[1])
- voodoo_update_ncc(voodoo, 1);
- voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0;
-
- queue_triangle(voodoo, &voodoo->params);
-}
-
-enum
-{
- BLIT_COMMAND_SCREEN_TO_SCREEN = 0,
- BLIT_COMMAND_CPU_TO_SCREEN = 1,
- BLIT_COMMAND_RECT_FILL = 2,
- BLIT_COMMAND_SGRAM_FILL = 3
-};
-
-enum
-{
- BLIT_SRC_1BPP = (0 << 3),
- BLIT_SRC_1BPP_BYTE_PACKED = (1 << 3),
- BLIT_SRC_16BPP = (2 << 3),
- BLIT_SRC_24BPP = (3 << 3),
- BLIT_SRC_24BPP_DITHER_2X2 = (4 << 3),
- BLIT_SRC_24BPP_DITHER_4X4 = (5 << 3)
-};
-
-enum
-{
- BLIT_SRC_RGB_ARGB = (0 << 6),
- BLIT_SRC_RGB_ABGR = (1 << 6),
- BLIT_SRC_RGB_RGBA = (2 << 6),
- BLIT_SRC_RGB_BGRA = (3 << 6)
-};
-
-enum
-{
- BLIT_COMMAND_MASK = 7,
- BLIT_SRC_FORMAT = (7 << 3),
- BLIT_SRC_RGB_FORMAT = (3 << 6),
- BLIT_SRC_CHROMA = (1 << 10),
- BLIT_DST_CHROMA = (1 << 12),
- BLIT_CLIPPING_ENABLED = (1 << 16)
-};
-
-enum
-{
- BLIT_ROP_DST_PASS = (1 << 0),
- BLIT_ROP_SRC_PASS = (1 << 1)
-};
-
-#define MIX(src_dat, dst_dat, rop) \
- switch (rop) \
- { \
- case 0x0: dst_dat = 0; break; \
- case 0x1: dst_dat = ~(src_dat | dst_dat); break; \
- case 0x2: dst_dat = ~src_dat & dst_dat; break; \
- case 0x3: dst_dat = ~src_dat; break; \
- case 0x4: dst_dat = src_dat & ~dst_dat; break; \
- case 0x5: dst_dat = ~dst_dat; break; \
- case 0x6: dst_dat = src_dat ^ dst_dat; break; \
- case 0x7: dst_dat = ~(src_dat & dst_dat); break; \
- case 0x8: dst_dat = src_dat & dst_dat; break; \
- case 0x9: dst_dat = ~(src_dat ^ dst_dat); break; \
- case 0xa: dst_dat = dst_dat; break; \
- case 0xb: dst_dat = ~src_dat | dst_dat; break; \
- case 0xc: dst_dat = src_dat; break; \
- case 0xd: dst_dat = src_dat | ~dst_dat; break; \
- case 0xe: dst_dat = src_dat | dst_dat; break; \
- case 0xf: dst_dat = 0xffff; break; \
- }
-
-static void blit_start(voodoo_t *voodoo)
-{
- uint64_t dat64;
- int size_x = ABS(voodoo->bltSizeX), size_y = ABS(voodoo->bltSizeY);
- int x_dir = (voodoo->bltSizeX > 0) ? 1 : -1;
- int y_dir = (voodoo->bltSizeY > 0) ? 1 : -1;
- int dst_x;
- int src_y = voodoo->bltSrcY & 0x7ff, dst_y = voodoo->bltDstY & 0x7ff;
- int src_stride = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcXYStride & 0x3f) * 32*2) : (voodoo->bltSrcXYStride & 0xff8);
- int dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32*2) : (voodoo->bltDstXYStride & 0xff8);
- uint32_t src_base_addr = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcBaseAddr & 0x3ff) << 12) : (voodoo->bltSrcBaseAddr & 0x3ffff8);
- uint32_t dst_base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8);
- int x, y;
-
-/* pclog("blit_start: command=%08x srcX=%i srcY=%i dstX=%i dstY=%i sizeX=%i sizeY=%i color=%04x,%04x\n",
- voodoo->bltCommand, voodoo->bltSrcX, voodoo->bltSrcY, voodoo->bltDstX, voodoo->bltDstY, voodoo->bltSizeX, voodoo->bltSizeY, voodoo->bltColorFg, voodoo->bltColorBg);*/
-
- wait_for_render_thread_idle(voodoo);
-
- switch (voodoo->bltCommand & BLIT_COMMAND_MASK)
- {
- case BLIT_COMMAND_SCREEN_TO_SCREEN:
- for (y = 0; y <= size_y; y++)
- {
- uint16_t *src = (uint16_t *)&voodoo->fb_mem[src_base_addr + src_y*src_stride];
- uint16_t *dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + dst_y*dst_stride];
- int src_x = voodoo->bltSrcX, dst_x = voodoo->bltDstX;
-
- for (x = 0; x <= size_x; x++)
- {
- uint16_t src_dat = src[src_x];
- uint16_t dst_dat = dst[dst_x];
- int rop = 0;
-
- if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED)
- {
- if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight ||
- dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY)
- goto skip_pixel_blit;
- }
-
- if (voodoo->bltCommand & BLIT_SRC_CHROMA)
- {
- int r = (src_dat >> 11);
- int g = (src_dat >> 5) & 0x3f;
- int b = src_dat & 0x1f;
-
- if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR &&
- g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG &&
- b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB)
- rop |= BLIT_ROP_SRC_PASS;
- }
- if (voodoo->bltCommand & BLIT_DST_CHROMA)
- {
- int r = (dst_dat >> 11);
- int g = (dst_dat >> 5) & 0x3f;
- int b = dst_dat & 0x1f;
-
- if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR &&
- g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG &&
- b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB)
- rop |= BLIT_ROP_DST_PASS;
- }
-
- MIX(src_dat, dst_dat, voodoo->bltRop[rop]);
-
- dst[dst_x] = dst_dat;
-skip_pixel_blit:
- src_x += x_dir;
- dst_x += x_dir;
- }
-
- src_y += y_dir;
- dst_y += y_dir;
- }
- break;
-
- case BLIT_COMMAND_CPU_TO_SCREEN:
- voodoo->blt.dst_x = voodoo->bltDstX;
- voodoo->blt.dst_y = voodoo->bltDstY;
- voodoo->blt.cur_x = 0;
- voodoo->blt.size_x = size_x;
- voodoo->blt.size_y = size_y;
- voodoo->blt.x_dir = x_dir;
- voodoo->blt.y_dir = y_dir;
- voodoo->blt.dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32*2) : (voodoo->bltDstXYStride & 0xff8);
- break;
-
- case BLIT_COMMAND_RECT_FILL:
- for (y = 0; y <= size_y; y++)
- {
- uint16_t *dst;
- int dst_x = voodoo->bltDstX;
-
- if (SLI_ENABLED)
- {
- if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) ||
- ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1)))
- goto skip_line_fill;
- dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + (dst_y >> 1) * dst_stride];
- }
- else
- dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + dst_y*dst_stride];
-
- for (x = 0; x <= size_x; x++)
- {
- if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED)
- {
- if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight ||
- dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY)
- goto skip_pixel_fill;
- }
-
- dst[dst_x] = voodoo->bltColorFg;
-skip_pixel_fill:
- dst_x += x_dir;
- }
-skip_line_fill:
- dst_y += y_dir;
- }
- break;
-
- case BLIT_COMMAND_SGRAM_FILL:
- /*32x32 tiles - 2kb*/
- dst_y = voodoo->bltDstY & 0x3ff;
- size_x = voodoo->bltSizeX & 0x1ff; //512*8 = 4kb
- size_y = voodoo->bltSizeY & 0x3ff;
-
- dat64 = voodoo->bltColorFg | ((uint64_t)voodoo->bltColorFg << 16) |
- ((uint64_t)voodoo->bltColorFg << 32) | ((uint64_t)voodoo->bltColorFg << 48);
-
- for (y = 0; y <= size_y; y++)
- {
- uint64_t *dst;
-
- /*This may be wrong*/
- if (!y)
- {
- dst_x = voodoo->bltDstX & 0x1ff;
- size_x = 511 - dst_x;
- }
- else if (y < size_y)
- {
- dst_x = 0;
- size_x = 511;
- }
- else
- {
- dst_x = 0;
- size_x = voodoo->bltSizeX & 0x1ff;
- }
-
- dst = (uint64_t *)&voodoo->fb_mem[(dst_y*512*8 + dst_x*8) & voodoo->fb_mask];
-
- for (x = 0; x <= size_x; x++)
- dst[x] = dat64;
-
- dst_y++;
- }
- break;
-
- default:
- fatal("bad blit command %08x\n", voodoo->bltCommand);
- }
-}
-
-static void blit_data(voodoo_t *voodoo, uint32_t data)
-{
- int src_bits = 32;
- uint32_t base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8);
- uint32_t addr;
- uint16_t *dst;
-
- if ((voodoo->bltCommand & BLIT_COMMAND_MASK) != BLIT_COMMAND_CPU_TO_SCREEN)
- return;
-
- if (SLI_ENABLED)
- {
- addr = base_addr + (voodoo->blt.dst_y >> 1) * voodoo->blt.dst_stride;
- dst = (uint16_t *)&voodoo->fb_mem[addr];
- }
- else
- {
- addr = base_addr + voodoo->blt.dst_y*voodoo->blt.dst_stride;
- dst = (uint16_t *)&voodoo->fb_mem[addr];
- }
-
- if (addr >= voodoo->front_offset && voodoo->row_width)
- {
- int y = (addr - voodoo->front_offset) / voodoo->row_width;
- if (y < voodoo->v_disp)
- voodoo->dirty_line[y] = 2;
- }
-
- while (src_bits && voodoo->blt.cur_x <= voodoo->blt.size_x)
- {
- int r = 0, g = 0, b = 0;
- uint16_t src_dat = 0, dst_dat;
- int x = (voodoo->blt.x_dir > 0) ? (voodoo->blt.dst_x + voodoo->blt.cur_x) : (voodoo->blt.dst_x - voodoo->blt.cur_x);
- int rop = 0;
-
- switch (voodoo->bltCommand & BLIT_SRC_FORMAT)
- {
- case BLIT_SRC_1BPP: case BLIT_SRC_1BPP_BYTE_PACKED:
- src_dat = (data & 1) ? voodoo->bltColorFg : voodoo->bltColorBg;
- data >>= 1;
- src_bits--;
- break;
- case BLIT_SRC_16BPP:
- switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT)
- {
- case BLIT_SRC_RGB_ARGB: case BLIT_SRC_RGB_RGBA:
- src_dat = data & 0xffff;
- break;
- case BLIT_SRC_RGB_ABGR: case BLIT_SRC_RGB_BGRA:
- src_dat = ((data & 0xf800) >> 11) | (data & 0x07c0) | ((data & 0x0038) << 11);
- break;
- }
- data >>= 16;
- src_bits -= 16;
- break;
- case BLIT_SRC_24BPP: case BLIT_SRC_24BPP_DITHER_2X2: case BLIT_SRC_24BPP_DITHER_4X4:
- switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT)
- {
- case BLIT_SRC_RGB_ARGB:
- r = (data >> 16) & 0xff;
- g = (data >> 8) & 0xff;
- b = data & 0xff;
- break;
- case BLIT_SRC_RGB_ABGR:
- r = data & 0xff;
- g = (data >> 8) & 0xff;
- b = (data >> 16) & 0xff;
- break;
- case BLIT_SRC_RGB_RGBA:
- r = (data >> 24) & 0xff;
- g = (data >> 16) & 0xff;
- b = (data >> 8) & 0xff;
- break;
- case BLIT_SRC_RGB_BGRA:
- r = (data >> 8) & 0xff;
- g = (data >> 16) & 0xff;
- b = (data >> 24) & 0xff;
- break;
- }
- switch (voodoo->bltCommand & BLIT_SRC_FORMAT)
- {
- case BLIT_SRC_24BPP:
- src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
- break;
- case BLIT_SRC_24BPP_DITHER_2X2:
- r = dither_rb2x2[r][voodoo->blt.dst_y & 1][x & 1];
- g = dither_g2x2[g][voodoo->blt.dst_y & 1][x & 1];
- b = dither_rb2x2[b][voodoo->blt.dst_y & 1][x & 1];
- src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
- break;
- case BLIT_SRC_24BPP_DITHER_4X4:
- r = dither_rb[r][voodoo->blt.dst_y & 3][x & 3];
- g = dither_g[g][voodoo->blt.dst_y & 3][x & 3];
- b = dither_rb[b][voodoo->blt.dst_y & 3][x & 3];
- src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
- break;
- }
- src_bits = 0;
- break;
- }
-
- if (SLI_ENABLED)
- {
- if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) ||
- ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1)))
- goto skip_pixel;
- }
-
- if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED)
- {
- if (x < voodoo->bltClipLeft || x >= voodoo->bltClipRight ||
- voodoo->blt.dst_y < voodoo->bltClipLowY || voodoo->blt.dst_y >= voodoo->bltClipHighY)
- goto skip_pixel;
- }
-
- dst_dat = dst[x];
-
- if (voodoo->bltCommand & BLIT_SRC_CHROMA)
- {
- r = (src_dat >> 11);
- g = (src_dat >> 5) & 0x3f;
- b = src_dat & 0x1f;
-
- if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR &&
- g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG &&
- b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB)
- rop |= BLIT_ROP_SRC_PASS;
- }
- if (voodoo->bltCommand & BLIT_DST_CHROMA)
- {
- r = (dst_dat >> 11);
- g = (dst_dat >> 5) & 0x3f;
- b = dst_dat & 0x1f;
-
- if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR &&
- g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG &&
- b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB)
- rop |= BLIT_ROP_DST_PASS;
- }
-
- MIX(src_dat, dst_dat, voodoo->bltRop[rop]);
-
- dst[x] = dst_dat;
-
-skip_pixel:
- voodoo->blt.cur_x++;
- }
-
- if (voodoo->blt.cur_x > voodoo->blt.size_x)
- {
- voodoo->blt.size_y--;
- if (voodoo->blt.size_y >= 0)
- {
- voodoo->blt.cur_x = 0;
- voodoo->blt.dst_y += voodoo->blt.y_dir;
- }
- }
-}
-
-enum
-{
- CHIP_FBI = 0x1,
- CHIP_TREX0 = 0x2,
- CHIP_TREX1 = 0x4,
- CHIP_TREX2 = 0x8
-};
-
-static void wait_for_swap_complete(voodoo_t *voodoo)
-{
- while (voodoo->swap_pending)
- {
- thread_wait_event(voodoo->wake_fifo_thread, -1);
- thread_reset_event(voodoo->wake_fifo_thread);
- if ((voodoo->swap_pending && voodoo->flush) || FIFO_ENTRIES >= 65536)
- {
- /*Main thread is waiting for FIFO to empty, so skip vsync wait and just swap*/
- memset(voodoo->dirty_line, 1, 1024);
- voodoo->front_offset = voodoo->params.front_offset;
- if (voodoo->swap_count > 0)
- voodoo->swap_count--;
- voodoo->swap_pending = 0;
- break;
- }
- }
-}
-
-static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
-{
- voodoo_t *voodoo = (voodoo_t *)p;
- union
- {
- uint32_t i;
- float f;
- } tempif;
- int ad21 = addr & (1 << 21);
- int chip = (addr >> 10) & 0xf;
- if (!chip)
- chip = 0xf;
-
- tempif.i = val;
-//pclog("voodoo_reg_write_l: addr=%08x val=%08x(%f) chip=%x\n", addr, val, tempif.f, chip);
- addr &= 0x3fc;
-
- if ((voodoo->fbiInit3 & FBIINIT3_REMAP) && addr < 0x100 && ad21)
- addr |= 0x400;
- switch (addr)
- {
- case SST_swapbufferCMD:
-// pclog(" start swap buffer command\n");
-
- if (TRIPLE_BUFFER)
- {
- voodoo->disp_buffer = (voodoo->disp_buffer + 1) % 3;
- voodoo->draw_buffer = (voodoo->draw_buffer + 1) % 3;
- }
- else
- {
- voodoo->disp_buffer = !voodoo->disp_buffer;
- voodoo->draw_buffer = !voodoo->draw_buffer;
- }
- voodoo_recalc(voodoo);
-
- voodoo->params.swapbufferCMD = val;
-
- pclog("Swap buffer %08x %d %p %i\n", val, voodoo->swap_count, &voodoo->swap_count, (voodoo == voodoo->set->voodoos[1]) ? 1 : 0);
-// voodoo->front_offset = params->front_offset;
- wait_for_render_thread_idle(voodoo);
- if (!(val & 1))
- {
- memset(voodoo->dirty_line, 1, 1024);
- voodoo->front_offset = voodoo->params.front_offset;
- if (voodoo->swap_count > 0)
- voodoo->swap_count--;
- }
- else if (TRIPLE_BUFFER)
- {
- if (voodoo->swap_pending)
- wait_for_swap_complete(voodoo);
-
- voodoo->swap_interval = (val >> 1) & 0xff;
- voodoo->swap_offset = voodoo->params.front_offset;
- voodoo->swap_pending = 1;
- }
- else
- {
- voodoo->swap_interval = (val >> 1) & 0xff;
- voodoo->swap_offset = voodoo->params.front_offset;
- voodoo->swap_pending = 1;
-
- wait_for_swap_complete(voodoo);
- }
- voodoo->cmd_read++;
- break;
-
- case SST_vertexAx: case SST_remap_vertexAx:
- voodoo->params.vertexAx = val & 0xffff;
- break;
- case SST_vertexAy: case SST_remap_vertexAy:
- voodoo->params.vertexAy = val & 0xffff;
- break;
- case SST_vertexBx: case SST_remap_vertexBx:
- voodoo->params.vertexBx = val & 0xffff;
- break;
- case SST_vertexBy: case SST_remap_vertexBy:
- voodoo->params.vertexBy = val & 0xffff;
- break;
- case SST_vertexCx: case SST_remap_vertexCx:
- voodoo->params.vertexCx = val & 0xffff;
- break;
- case SST_vertexCy: case SST_remap_vertexCy:
- voodoo->params.vertexCy = val & 0xffff;
- break;
-
- case SST_startR: case SST_remap_startR:
- voodoo->params.startR = val & 0xffffff;
- break;
- case SST_startG: case SST_remap_startG:
- voodoo->params.startG = val & 0xffffff;
- break;
- case SST_startB: case SST_remap_startB:
- voodoo->params.startB = val & 0xffffff;
- break;
- case SST_startZ: case SST_remap_startZ:
- voodoo->params.startZ = val;
- break;
- case SST_startA: case SST_remap_startA:
- voodoo->params.startA = val & 0xffffff;
- break;
- case SST_startS: case SST_remap_startS:
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].startS = ((int64_t)(int32_t)val) << 14;
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].startS = ((int64_t)(int32_t)val) << 14;
- break;
- case SST_startT: case SST_remap_startT:
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].startT = ((int64_t)(int32_t)val) << 14;
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].startT = ((int64_t)(int32_t)val) << 14;
- break;
- case SST_startW: case SST_remap_startW:
- if (chip & CHIP_FBI)
- voodoo->params.startW = (int64_t)(int32_t)val << 2;
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].startW = (int64_t)(int32_t)val << 2;
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].startW = (int64_t)(int32_t)val << 2;
- break;
-
- case SST_dRdX: case SST_remap_dRdX:
- voodoo->params.dRdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
- break;
- case SST_dGdX: case SST_remap_dGdX:
- voodoo->params.dGdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
- break;
- case SST_dBdX: case SST_remap_dBdX:
- voodoo->params.dBdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
- break;
- case SST_dZdX: case SST_remap_dZdX:
- voodoo->params.dZdX = val;
- break;
- case SST_dAdX: case SST_remap_dAdX:
- voodoo->params.dAdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
- break;
- case SST_dSdX: case SST_remap_dSdX:
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].dSdX = ((int64_t)(int32_t)val) << 14;
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].dSdX = ((int64_t)(int32_t)val) << 14;
- break;
- case SST_dTdX: case SST_remap_dTdX:
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].dTdX = ((int64_t)(int32_t)val) << 14;
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].dTdX = ((int64_t)(int32_t)val) << 14;
- break;
- case SST_dWdX: case SST_remap_dWdX:
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].dWdX = (int64_t)(int32_t)val << 2;
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].dWdX = (int64_t)(int32_t)val << 2;
- if (chip & CHIP_FBI)
- voodoo->params.dWdX = (int64_t)(int32_t)val << 2;
- break;
-
- case SST_dRdY: case SST_remap_dRdY:
- voodoo->params.dRdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
- break;
- case SST_dGdY: case SST_remap_dGdY:
- voodoo->params.dGdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
- break;
- case SST_dBdY: case SST_remap_dBdY:
- voodoo->params.dBdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
- break;
- case SST_dZdY: case SST_remap_dZdY:
- voodoo->params.dZdY = val;
- break;
- case SST_dAdY: case SST_remap_dAdY:
- voodoo->params.dAdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
- break;
- case SST_dSdY: case SST_remap_dSdY:
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].dSdY = ((int64_t)(int32_t)val) << 14;
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].dSdY = ((int64_t)(int32_t)val) << 14;
- break;
- case SST_dTdY: case SST_remap_dTdY:
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].dTdY = ((int64_t)(int32_t)val) << 14;
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].dTdY = ((int64_t)(int32_t)val) << 14;
- break;
- case SST_dWdY: case SST_remap_dWdY:
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].dWdY = (int64_t)(int32_t)val << 2;
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].dWdY = (int64_t)(int32_t)val << 2;
- if (chip & CHIP_FBI)
- voodoo->params.dWdY = (int64_t)(int32_t)val << 2;
- break;
-
- case SST_triangleCMD: case SST_remap_triangleCMD:
- voodoo->params.sign = val & (1 << 31);
-
- if (voodoo->ncc_dirty[0])
- voodoo_update_ncc(voodoo, 0);
- if (voodoo->ncc_dirty[1])
- voodoo_update_ncc(voodoo, 1);
- voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0;
-
- queue_triangle(voodoo, &voodoo->params);
-
- voodoo->cmd_read++;
- break;
-
- case SST_fvertexAx: case SST_remap_fvertexAx:
- voodoo->fvertexAx.i = val;
- voodoo->params.vertexAx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexAx.f * 16.0f) & 0xffff;
- break;
- case SST_fvertexAy: case SST_remap_fvertexAy:
- voodoo->fvertexAy.i = val;
- voodoo->params.vertexAy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexAy.f * 16.0f) & 0xffff;
- break;
- case SST_fvertexBx: case SST_remap_fvertexBx:
- voodoo->fvertexBx.i = val;
- voodoo->params.vertexBx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexBx.f * 16.0f) & 0xffff;
- break;
- case SST_fvertexBy: case SST_remap_fvertexBy:
- voodoo->fvertexBy.i = val;
- voodoo->params.vertexBy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexBy.f * 16.0f) & 0xffff;
- break;
- case SST_fvertexCx: case SST_remap_fvertexCx:
- voodoo->fvertexCx.i = val;
- voodoo->params.vertexCx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexCx.f * 16.0f) & 0xffff;
- break;
- case SST_fvertexCy: case SST_remap_fvertexCy:
- voodoo->fvertexCy.i = val;
- voodoo->params.vertexCy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexCy.f * 16.0f) & 0xffff;
- break;
-
- case SST_fstartR: case SST_remap_fstartR:
- tempif.i = val;
- voodoo->params.startR = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fstartG: case SST_remap_fstartG:
- tempif.i = val;
- voodoo->params.startG = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fstartB: case SST_remap_fstartB:
- tempif.i = val;
- voodoo->params.startB = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fstartZ: case SST_remap_fstartZ:
- tempif.i = val;
- voodoo->params.startZ = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fstartA: case SST_remap_fstartA:
- tempif.i = val;
- voodoo->params.startA = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fstartS: case SST_remap_fstartS:
- tempif.i = val;
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].startS = (int64_t)(tempif.f * 4294967296.0f);
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].startS = (int64_t)(tempif.f * 4294967296.0f);
- break;
- case SST_fstartT: case SST_remap_fstartT:
- tempif.i = val;
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].startT = (int64_t)(tempif.f * 4294967296.0f);
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].startT = (int64_t)(tempif.f * 4294967296.0f);
- break;
- case SST_fstartW: case SST_remap_fstartW:
- tempif.i = val;
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].startW = (int64_t)(tempif.f * 4294967296.0f);
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].startW = (int64_t)(tempif.f * 4294967296.0f);
- if (chip & CHIP_FBI)
- voodoo->params.startW = (int64_t)(tempif.f * 4294967296.0f);
- break;
-
- case SST_fdRdX: case SST_remap_fdRdX:
- tempif.i = val;
- voodoo->params.dRdX = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fdGdX: case SST_remap_fdGdX:
- tempif.i = val;
- voodoo->params.dGdX = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fdBdX: case SST_remap_fdBdX:
- tempif.i = val;
- voodoo->params.dBdX = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fdZdX: case SST_remap_fdZdX:
- tempif.i = val;
- voodoo->params.dZdX = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fdAdX: case SST_remap_fdAdX:
- tempif.i = val;
- voodoo->params.dAdX = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fdSdX: case SST_remap_fdSdX:
- tempif.i = val;
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].dSdX = (int64_t)(tempif.f * 4294967296.0f);
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].dSdX = (int64_t)(tempif.f * 4294967296.0f);
- break;
- case SST_fdTdX: case SST_remap_fdTdX:
- tempif.i = val;
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].dTdX = (int64_t)(tempif.f * 4294967296.0f);
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].dTdX = (int64_t)(tempif.f * 4294967296.0f);
- break;
- case SST_fdWdX: case SST_remap_fdWdX:
- tempif.i = val;
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].dWdX = (int64_t)(tempif.f * 4294967296.0f);
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].dWdX = (int64_t)(tempif.f * 4294967296.0f);
- if (chip & CHIP_FBI)
- voodoo->params.dWdX = (int64_t)(tempif.f * 4294967296.0f);
- break;
-
- case SST_fdRdY: case SST_remap_fdRdY:
- tempif.i = val;
- voodoo->params.dRdY = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fdGdY: case SST_remap_fdGdY:
- tempif.i = val;
- voodoo->params.dGdY = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fdBdY: case SST_remap_fdBdY:
- tempif.i = val;
- voodoo->params.dBdY = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fdZdY: case SST_remap_fdZdY:
- tempif.i = val;
- voodoo->params.dZdY = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fdAdY: case SST_remap_fdAdY:
- tempif.i = val;
- voodoo->params.dAdY = (int32_t)(tempif.f * 4096.0f);
- break;
- case SST_fdSdY: case SST_remap_fdSdY:
- tempif.i = val;
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].dSdY = (int64_t)(tempif.f * 4294967296.0f);
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].dSdY = (int64_t)(tempif.f * 4294967296.0f);
- break;
- case SST_fdTdY: case SST_remap_fdTdY:
- tempif.i = val;
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].dTdY = (int64_t)(tempif.f * 4294967296.0f);
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].dTdY = (int64_t)(tempif.f * 4294967296.0f);
- break;
- case SST_fdWdY: case SST_remap_fdWdY:
- tempif.i = val;
- if (chip & CHIP_TREX0)
- voodoo->params.tmu[0].dWdY = (int64_t)(tempif.f * 4294967296.0f);
- if (chip & CHIP_TREX1)
- voodoo->params.tmu[1].dWdY = (int64_t)(tempif.f * 4294967296.0f);
- if (chip & CHIP_FBI)
- voodoo->params.dWdY = (int64_t)(tempif.f * 4294967296.0f);
- break;
-
- case SST_ftriangleCMD:
- voodoo->params.sign = val & (1 << 31);
-
- if (voodoo->ncc_dirty[0])
- voodoo_update_ncc(voodoo, 0);
- if (voodoo->ncc_dirty[1])
- voodoo_update_ncc(voodoo, 1);
- voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0;
-
- queue_triangle(voodoo, &voodoo->params);
-
- voodoo->cmd_read++;
- break;
-
- case SST_fbzColorPath:
- voodoo->params.fbzColorPath = val;
- voodoo->rgb_sel = val & 3;
- break;
-
- case SST_fogMode:
- voodoo->params.fogMode = val;
- break;
- case SST_alphaMode:
- voodoo->params.alphaMode = val;
- break;
- case SST_fbzMode:
- voodoo->params.fbzMode = val;
- voodoo_recalc(voodoo);
- break;
- case SST_lfbMode:
- voodoo->lfbMode = val;
- voodoo_recalc(voodoo);
- break;
-
- case SST_clipLeftRight:
- if (voodoo->type >= VOODOO_2)
- {
- voodoo->params.clipRight = val & 0xfff;
- voodoo->params.clipLeft = (val >> 16) & 0xfff;
- }
- else
- {
- voodoo->params.clipRight = val & 0x3ff;
- voodoo->params.clipLeft = (val >> 16) & 0x3ff;
- }
- break;
- case SST_clipLowYHighY:
- if (voodoo->type >= VOODOO_2)
- {
- voodoo->params.clipHighY = val & 0xfff;
- voodoo->params.clipLowY = (val >> 16) & 0xfff;
- }
- else
- {
- voodoo->params.clipHighY = val & 0x3ff;
- voodoo->params.clipLowY = (val >> 16) & 0x3ff;
- }
- break;
-
- case SST_nopCMD:
- voodoo->cmd_read++;
- voodoo->fbiPixelsIn = 0;
- voodoo->fbiChromaFail = 0;
- voodoo->fbiZFuncFail = 0;
- voodoo->fbiAFuncFail = 0;
- voodoo->fbiPixelsOut = 0;
- break;
- case SST_fastfillCMD:
- wait_for_render_thread_idle(voodoo);
- voodoo_fastfill(voodoo, &voodoo->params);
- voodoo->cmd_read++;
- break;
-
- case SST_fogColor:
- voodoo->params.fogColor.r = (val >> 16) & 0xff;
- voodoo->params.fogColor.g = (val >> 8) & 0xff;
- voodoo->params.fogColor.b = val & 0xff;
- break;
-
- case SST_zaColor:
- voodoo->params.zaColor = val;
- break;
- case SST_chromaKey:
- voodoo->params.chromaKey_r = (val >> 16) & 0xff;
- voodoo->params.chromaKey_g = (val >> 8) & 0xff;
- voodoo->params.chromaKey_b = val & 0xff;
- voodoo->params.chromaKey = val & 0xffffff;
- break;
- case SST_stipple:
- voodoo->params.stipple = val;
- break;
- case SST_color0:
- voodoo->params.color0 = val;
- break;
- case SST_color1:
- voodoo->params.color1 = val;
- break;
-
- case SST_fogTable00: case SST_fogTable01: case SST_fogTable02: case SST_fogTable03:
- case SST_fogTable04: case SST_fogTable05: case SST_fogTable06: case SST_fogTable07:
- case SST_fogTable08: case SST_fogTable09: case SST_fogTable0a: case SST_fogTable0b:
- case SST_fogTable0c: case SST_fogTable0d: case SST_fogTable0e: case SST_fogTable0f:
- case SST_fogTable10: case SST_fogTable11: case SST_fogTable12: case SST_fogTable13:
- case SST_fogTable14: case SST_fogTable15: case SST_fogTable16: case SST_fogTable17:
- case SST_fogTable18: case SST_fogTable19: case SST_fogTable1a: case SST_fogTable1b:
- case SST_fogTable1c: case SST_fogTable1d: case SST_fogTable1e: case SST_fogTable1f:
- addr = (addr - SST_fogTable00) >> 1;
- voodoo->params.fogTable[addr].dfog = val & 0xff;
- voodoo->params.fogTable[addr].fog = (val >> 8) & 0xff;
- voodoo->params.fogTable[addr+1].dfog = (val >> 16) & 0xff;
- voodoo->params.fogTable[addr+1].fog = (val >> 24) & 0xff;
- break;
-
- case SST_clutData:
- voodoo->clutData[(val >> 24) & 0x3f].b = val & 0xff;
- voodoo->clutData[(val >> 24) & 0x3f].g = (val >> 8) & 0xff;
- voodoo->clutData[(val >> 24) & 0x3f].r = (val >> 16) & 0xff;
- if (val & 0x20000000)
- {
- voodoo->clutData[(val >> 24) & 0x3f].b = 255;
- voodoo->clutData[(val >> 24) & 0x3f].g = 255;
- voodoo->clutData[(val >> 24) & 0x3f].r = 255;
- }
- voodoo->clutData_dirty = 1;
- break;
-
- case SST_sSetupMode:
- voodoo->sSetupMode = val;
- break;
- case SST_sVx:
- tempif.i = val;
- voodoo->verts[3].sVx = tempif.f;
-// pclog("sVx[%i]=%f\n", voodoo->vertex_num, tempif.f);
- break;
- case SST_sVy:
- tempif.i = val;
- voodoo->verts[3].sVy = tempif.f;
-// pclog("sVy[%i]=%f\n", voodoo->vertex_num, tempif.f);
- break;
- case SST_sARGB:
- voodoo->verts[3].sBlue = (float)(val & 0xff);
- voodoo->verts[3].sGreen = (float)((val >> 8) & 0xff);
- voodoo->verts[3].sRed = (float)((val >> 16) & 0xff);
- voodoo->verts[3].sAlpha = (float)((val >> 24) & 0xff);
- break;
- case SST_sRed:
- tempif.i = val;
- voodoo->verts[3].sRed = tempif.f;
- break;
- case SST_sGreen:
- tempif.i = val;
- voodoo->verts[3].sGreen = tempif.f;
- break;
- case SST_sBlue:
- tempif.i = val;
- voodoo->verts[3].sBlue = tempif.f;
- break;
- case SST_sAlpha:
- tempif.i = val;
- voodoo->verts[3].sAlpha = tempif.f;
- break;
- case SST_sVz:
- tempif.i = val;
- voodoo->verts[3].sVz = tempif.f;
- break;
- case SST_sWb:
- tempif.i = val;
- voodoo->verts[3].sWb = tempif.f;
- break;
- case SST_sW0:
- tempif.i = val;
- voodoo->verts[3].sW0 = tempif.f;
- break;
- case SST_sS0:
- tempif.i = val;
- voodoo->verts[3].sS0 = tempif.f;
- break;
- case SST_sT0:
- tempif.i = val;
- voodoo->verts[3].sT0 = tempif.f;
- break;
- case SST_sW1:
- tempif.i = val;
- voodoo->verts[3].sW1 = tempif.f;
- break;
- case SST_sS1:
- tempif.i = val;
- voodoo->verts[3].sS1 = tempif.f;
- break;
- case SST_sT1:
- tempif.i = val;
- voodoo->verts[3].sT1 = tempif.f;
- break;
-
- case SST_sBeginTriCMD:
-// pclog("sBeginTriCMD %i %f\n", voodoo->vertex_num, voodoo->verts[4].sVx);
- voodoo->verts[0] = voodoo->verts[3];
- voodoo->vertex_num = 1;
- voodoo->num_verticies = 1;
- break;
- case SST_sDrawTriCMD:
-// pclog("sDrawTriCMD %i %i %i\n", voodoo->num_verticies, voodoo->vertex_num, voodoo->sSetupMode & SETUPMODE_STRIP_MODE);
- if (voodoo->vertex_num == 3)
- voodoo->vertex_num = (voodoo->sSetupMode & SETUPMODE_STRIP_MODE) ? 1 : 0;
- voodoo->verts[voodoo->vertex_num] = voodoo->verts[3];
-
- voodoo->num_verticies++;
- voodoo->vertex_num++;
- if (voodoo->num_verticies == 3)
- {
-// pclog("triangle_setup\n");
- triangle_setup(voodoo);
-
- voodoo->num_verticies = 2;
- }
- if (voodoo->vertex_num == 4)
- fatal("sDrawTriCMD overflow\n");
- break;
-
- case SST_bltSrcBaseAddr:
- voodoo->bltSrcBaseAddr = val & 0x3fffff;
- break;
- case SST_bltDstBaseAddr:
-// pclog("Write bltDstBaseAddr %08x\n", val);
- voodoo->bltDstBaseAddr = val & 0x3fffff;
- break;
- case SST_bltXYStrides:
- voodoo->bltSrcXYStride = val & 0xfff;
- voodoo->bltDstXYStride = (val >> 16) & 0xfff;
-// pclog("Write bltXYStrides %08x\n", val);
- break;
- case SST_bltSrcChromaRange:
- voodoo->bltSrcChromaRange = val;
- voodoo->bltSrcChromaMinB = val & 0x1f;
- voodoo->bltSrcChromaMinG = (val >> 5) & 0x3f;
- voodoo->bltSrcChromaMinR = (val >> 11) & 0x1f;
- voodoo->bltSrcChromaMaxB = (val >> 16) & 0x1f;
- voodoo->bltSrcChromaMaxG = (val >> 21) & 0x3f;
- voodoo->bltSrcChromaMaxR = (val >> 27) & 0x1f;
- break;
- case SST_bltDstChromaRange:
- voodoo->bltDstChromaRange = val;
- voodoo->bltDstChromaMinB = val & 0x1f;
- voodoo->bltDstChromaMinG = (val >> 5) & 0x3f;
- voodoo->bltDstChromaMinR = (val >> 11) & 0x1f;
- voodoo->bltDstChromaMaxB = (val >> 16) & 0x1f;
- voodoo->bltDstChromaMaxG = (val >> 21) & 0x3f;
- voodoo->bltDstChromaMaxR = (val >> 27) & 0x1f;
- break;
- case SST_bltClipX:
- voodoo->bltClipRight = val & 0xfff;
- voodoo->bltClipLeft = (val >> 16) & 0xfff;
- break;
- case SST_bltClipY:
- voodoo->bltClipHighY = val & 0xfff;
- voodoo->bltClipLowY = (val >> 16) & 0xfff;
- break;
-
- case SST_bltSrcXY:
- voodoo->bltSrcX = val & 0x7ff;
- voodoo->bltSrcY = (val >> 16) & 0x7ff;
- break;
- case SST_bltDstXY:
-// pclog("Write bltDstXY %08x\n", val);
- voodoo->bltDstX = val & 0x7ff;
- voodoo->bltDstY = (val >> 16) & 0x7ff;
- if (val & (1 << 31))
- blit_start(voodoo);
- break;
- case SST_bltSize:
-// pclog("Write bltSize %08x\n", val);
- voodoo->bltSizeX = val & 0xfff;
- if (voodoo->bltSizeX & 0x800)
- voodoo->bltSizeX |= 0xfffff000;
- voodoo->bltSizeY = (val >> 16) & 0xfff;
- if (voodoo->bltSizeY & 0x800)
- voodoo->bltSizeY |= 0xfffff000;
- if (val & (1 << 31))
- blit_start(voodoo);
- break;
- case SST_bltRop:
- voodoo->bltRop[0] = val & 0xf;
- voodoo->bltRop[1] = (val >> 4) & 0xf;
- voodoo->bltRop[2] = (val >> 8) & 0xf;
- voodoo->bltRop[3] = (val >> 12) & 0xf;
- break;
- case SST_bltColor:
-// pclog("Write bltColor %08x\n", val);
- voodoo->bltColorFg = val & 0xffff;
- voodoo->bltColorBg = (val >> 16) & 0xffff;
- break;
-
- case SST_bltCommand:
- voodoo->bltCommand = val;
-// pclog("Write bltCommand %08x\n", val);
- if (val & (1 << 31))
- blit_start(voodoo);
- break;
- case SST_bltData:
- blit_data(voodoo, val);
- break;
-
- case SST_textureMode:
- if (chip & CHIP_TREX0)
- {
- voodoo->params.textureMode[0] = val;
- voodoo->params.tformat[0] = (val >> 8) & 0xf;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->params.textureMode[1] = val;
- voodoo->params.tformat[1] = (val >> 8) & 0xf;
- }
- break;
- case SST_tLOD:
- if (chip & CHIP_TREX0)
- {
- voodoo->params.tLOD[0] = val;
- voodoo_recalc_tex(voodoo, 0);
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->params.tLOD[1] = val;
- voodoo_recalc_tex(voodoo, 1);
- }
- break;
- case SST_tDetail:
- if (chip & CHIP_TREX0)
- {
- voodoo->params.detail_max[0] = val & 0xff;
- voodoo->params.detail_bias[0] = (val >> 8) & 0x3f;
- voodoo->params.detail_scale[0] = (val >> 14) & 7;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->params.detail_max[1] = val & 0xff;
- voodoo->params.detail_bias[1] = (val >> 8) & 0x3f;
- voodoo->params.detail_scale[1] = (val >> 14) & 7;
- }
- break;
- case SST_texBaseAddr:
- if (chip & CHIP_TREX0)
- {
- voodoo->params.texBaseAddr[0] = (val & 0x7ffff) << 3;
- voodoo_recalc_tex(voodoo, 0);
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->params.texBaseAddr[1] = (val & 0x7ffff) << 3;
- voodoo_recalc_tex(voodoo, 1);
- }
- break;
- case SST_texBaseAddr1:
- if (chip & CHIP_TREX0)
- {
- voodoo->params.texBaseAddr1[0] = (val & 0x7ffff) << 3;
- voodoo_recalc_tex(voodoo, 0);
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->params.texBaseAddr1[1] = (val & 0x7ffff) << 3;
- voodoo_recalc_tex(voodoo, 1);
- }
- break;
- case SST_texBaseAddr2:
- if (chip & CHIP_TREX0)
- {
- voodoo->params.texBaseAddr2[0] = (val & 0x7ffff) << 3;
- voodoo_recalc_tex(voodoo, 0);
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->params.texBaseAddr2[1] = (val & 0x7ffff) << 3;
- voodoo_recalc_tex(voodoo, 1);
- }
- break;
- case SST_texBaseAddr38:
- if (chip & CHIP_TREX0)
- {
- voodoo->params.texBaseAddr38[0] = (val & 0x7ffff) << 3;
- voodoo_recalc_tex(voodoo, 0);
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->params.texBaseAddr38[1] = (val & 0x7ffff) << 3;
- voodoo_recalc_tex(voodoo, 1);
- }
- break;
-
- case SST_trexInit1:
- if (chip & CHIP_TREX0)
- voodoo->trexInit1[0] = val;
- if (chip & CHIP_TREX1)
- voodoo->trexInit1[1] = val;
- break;
-
- case SST_nccTable0_Y0:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][0].y[0] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][0].y[0] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- case SST_nccTable0_Y1:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][0].y[1] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][0].y[1] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- case SST_nccTable0_Y2:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][0].y[2] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][0].y[2] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- case SST_nccTable0_Y3:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][0].y[3] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][0].y[3] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
-
- case SST_nccTable0_I0:
- if (!(val & (1 << 31)))
- {
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][0].i[0] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][0].i[0] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- }
- case SST_nccTable0_I2:
- if (!(val & (1 << 31)))
- {
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][0].i[2] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][0].i[2] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- }
- case SST_nccTable0_Q0:
- if (!(val & (1 << 31)))
- {
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][0].q[0] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][0].q[0] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- }
- case SST_nccTable0_Q2:
- if (!(val & (1 << 31)))
- {
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][0].i[2] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][0].i[2] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- }
- if (val & (1 << 31))
- {
- int p = (val >> 23) & 0xfe;
- if (chip & CHIP_TREX0)
- {
- voodoo->palette[0][p].u = val | 0xff000000;
- voodoo->palette_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->palette[1][p].u = val | 0xff000000;
- voodoo->palette_dirty[1] = 1;
- }
- }
- break;
-
- case SST_nccTable0_I1:
- if (!(val & (1 << 31)))
- {
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][0].i[1] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][0].i[1] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- }
- case SST_nccTable0_I3:
- if (!(val & (1 << 31)))
- {
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][0].i[3] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][0].i[3] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- }
- case SST_nccTable0_Q1:
- if (!(val & (1 << 31)))
- {
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][0].q[1] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][0].q[1] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- }
- case SST_nccTable0_Q3:
- if (!(val & (1 << 31)))
- {
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][0].q[3] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][0].q[3] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- }
- if (val & (1 << 31))
- {
- int p = ((val >> 23) & 0xfe) | 0x01;
- if (chip & CHIP_TREX0)
- {
- voodoo->palette[0][p].u = val | 0xff000000;
- voodoo->palette_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->palette[1][p].u = val | 0xff000000;
- voodoo->palette_dirty[1] = 1;
- }
- }
- break;
-
- case SST_nccTable1_Y0:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][1].y[0] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][1].y[0] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- case SST_nccTable1_Y1:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][1].y[1] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][1].y[1] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- case SST_nccTable1_Y2:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][1].y[2] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][1].y[2] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- case SST_nccTable1_Y3:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][1].y[3] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][1].y[3] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- case SST_nccTable1_I0:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][1].i[0] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][1].i[0] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- case SST_nccTable1_I1:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][1].i[1] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][1].i[1] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- case SST_nccTable1_I2:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][1].i[2] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][1].i[2] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- case SST_nccTable1_I3:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][1].i[3] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][1].i[3] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- case SST_nccTable1_Q0:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][1].q[0] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][1].q[0] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- case SST_nccTable1_Q1:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][1].q[1] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][1].q[1] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- case SST_nccTable1_Q2:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][1].q[2] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][1].q[2] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
- case SST_nccTable1_Q3:
- if (chip & CHIP_TREX0)
- {
- voodoo->nccTable[0][1].q[3] = val;
- voodoo->ncc_dirty[0] = 1;
- }
- if (chip & CHIP_TREX1)
- {
- voodoo->nccTable[1][1].q[3] = val;
- voodoo->ncc_dirty[1] = 1;
- }
- break;
-
- case SST_userIntrCMD:
- fatal("userIntrCMD write %08x from FIFO\n", val);
- break;
- }
-}
-
-
-static uint16_t voodoo_fb_readw(uint32_t addr, void *p)
-{
- voodoo_t *voodoo = (voodoo_t *)p;
- int x, y;
- uint32_t read_addr;
- uint16_t temp;
-
- x = (addr >> 1) & 0x3ff;
- y = (addr >> 11) & 0x3ff;
-
- if (SLI_ENABLED)
- {
- voodoo_set_t *set = voodoo->set;
-
- if (y & 1)
- voodoo = set->voodoos[1];
- else
- voodoo = set->voodoos[0];
-
- y >>= 1;
- }
-
- read_addr = voodoo->fb_read_offset + (x << 1) + (y * voodoo->row_width);
-
- if (read_addr > voodoo->fb_mask)
- return 0xffff;
-
- temp = *(uint16_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]);
-
-// pclog("voodoo_fb_readw : %08X %08X %i %i %08X %08X %08x:%08x %i\n", addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++);
- return temp;
-}
-static uint32_t voodoo_fb_readl(uint32_t addr, void *p)
-{
- voodoo_t *voodoo = (voodoo_t *)p;
- int x, y;
- uint32_t read_addr;
- uint32_t temp;
-
- x = addr & 0x7fe;
- y = (addr >> 11) & 0x3ff;
-
- if (SLI_ENABLED)
- {
- voodoo_set_t *set = voodoo->set;
-
- if (y & 1)
- voodoo = set->voodoos[1];
- else
- voodoo = set->voodoos[0];
-
- y >>= 1;
- }
-
- read_addr = voodoo->fb_read_offset + x + (y * voodoo->row_width);
-
- if (read_addr > voodoo->fb_mask)
- return 0xffffffff;
-
- temp = *(uint32_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]);
-
-// pclog("voodoo_fb_readl : %08X %08x %08X x=%i y=%i %08X %08X %08x:%08x %i ro=%08x rw=%i\n", addr, read_addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++, voodoo->fb_read_offset, voodoo->row_width);
- return temp;
-}
-
-static inline uint16_t do_dither(voodoo_params_t *params, rgba8_t col, int x, int y)
-{
- int r, g, b;
-
- if (dither)
- {
- if (dither2x2)
- {
- r = dither_rb2x2[col.r][y & 1][x & 1];
- g = dither_g2x2[col.g][y & 1][x & 1];
- b = dither_rb2x2[col.b][y & 1][x & 1];
- }
- else
- {
- r = dither_rb[col.r][y & 3][x & 3];
- g = dither_g[col.g][y & 3][x & 3];
- b = dither_rb[col.b][y & 3][x & 3];
- }
- }
- else
- {
- r = col.r >> 3;
- g = col.g >> 2;
- b = col.b >> 3;
- }
-
- return b | (g << 5) | (r << 11);
-}
-
-static void voodoo_fb_writew(uint32_t addr, uint16_t val, void *p)
-{
- voodoo_t *voodoo = (voodoo_t *)p;
- voodoo_params_t *params = &voodoo->params;
- int x, y;
- uint32_t write_addr, write_addr_aux;
- rgba8_t colour_data;
- uint16_t depth_data;
- uint8_t alpha_data;
- int write_mask = 0;
-
- colour_data.r = colour_data.g = colour_data.b = colour_data.a = 0;
-
- depth_data = voodoo->params.zaColor & 0xffff;
- alpha_data = voodoo->params.zaColor >> 24;
-
-// while (!RB_EMPTY)
-// thread_reset_event(voodoo->not_full_event);
-
-// pclog("voodoo_fb_writew : %08X %04X\n", addr, val);
-
-
- switch (voodoo->lfbMode & LFB_FORMAT_MASK)
- {
- case LFB_FORMAT_RGB565:
- colour_data = rgb565[val];
- alpha_data = 0xff;
- write_mask = LFB_WRITE_COLOUR;
- break;
- case LFB_FORMAT_RGB555:
- colour_data = argb1555[val];
- alpha_data = 0xff;
- write_mask = LFB_WRITE_COLOUR;
- break;
- case LFB_FORMAT_ARGB1555:
- colour_data = argb1555[val];
- alpha_data = colour_data.a;
- write_mask = LFB_WRITE_COLOUR;
- break;
- case LFB_FORMAT_DEPTH:
- depth_data = val;
- write_mask = LFB_WRITE_DEPTH;
- break;
-
- default:
- fatal("voodoo_fb_writew : bad LFB format %08X\n", voodoo->lfbMode);
- }
-
- x = addr & 0x7fe;
- y = (addr >> 11) & 0x3ff;
-
- if (SLI_ENABLED)
- {
- if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) ||
- ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1)))
- return;
- y >>= 1;
- }
-
-
- if (voodoo->fb_write_offset == voodoo->params.front_offset)
- voodoo->dirty_line[y] = 1;
-
- write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width);
- write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width);
-
-// pclog("fb_writew %08x %i %i %i %08x\n", addr, x, y, voodoo->row_width, write_addr);
-
- if (voodoo->lfbMode & 0x100)
- {
- {
- rgba8_t write_data = colour_data;
- uint16_t new_depth = depth_data;
-
- if (params->fbzMode & FBZ_DEPTH_ENABLE)
- {
- uint16_t old_depth = *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]);
-
- DEPTH_TEST(new_depth);
- }
-
- if ((params->fbzMode & FBZ_CHROMAKEY) &&
- write_data.r == params->chromaKey_r &&
- write_data.g == params->chromaKey_g &&
- write_data.b == params->chromaKey_b)
- goto skip_pixel;
-
- if (params->fogMode & FOG_ENABLE)
- {
- int32_t z = new_depth << 12;
- int64_t w_depth = (int64_t)(int32_t)new_depth;
- int32_t ia = alpha_data << 12;
-
- APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth);
- }
-
- if (params->alphaMode & 1)
- ALPHA_TEST(alpha_data);
-
- if (params->alphaMode & (1 << 4))
- {
- uint16_t dat = *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]);
- int dest_r, dest_g, dest_b, dest_a;
-
- dest_r = (dat >> 8) & 0xf8;
- dest_g = (dat >> 3) & 0xfc;
- dest_b = (dat << 3) & 0xf8;
- dest_r |= (dest_r >> 5);
- dest_g |= (dest_g >> 6);
- dest_b |= (dest_b >> 5);
- dest_a = 0xff;
-
- ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data);
- }
-
- if (params->fbzMode & FBZ_RGB_WMASK)
- *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, x >> 1, y);
- if (params->fbzMode & FBZ_DEPTH_WMASK)
- *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth;
-
-skip_pixel:
- x = x;
- }
- }
- else
- {
- if (write_mask & LFB_WRITE_COLOUR)
- *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data, x >> 1, y);
- if (write_mask & LFB_WRITE_DEPTH)
- *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data;
- }
-}
-
-
-static void voodoo_fb_writel(uint32_t addr, uint32_t val, void *p)
-{
- voodoo_t *voodoo = (voodoo_t *)p;
- voodoo_params_t *params = &voodoo->params;
- int x, y;
- uint32_t write_addr, write_addr_aux;
- rgba8_t colour_data[2];
- uint16_t depth_data[2];
- uint8_t alpha_data[2];
- int write_mask = 0, count = 1;
-
- depth_data[0] = depth_data[1] = voodoo->params.zaColor & 0xffff;
- alpha_data[0] = alpha_data[1] = voodoo->params.zaColor >> 24;
-// while (!RB_EMPTY)
-// thread_reset_event(voodoo->not_full_event);
-
-// pclog("voodoo_fb_writel : %08X %08X\n", addr, val);
-
- switch (voodoo->lfbMode & LFB_FORMAT_MASK)
- {
- case LFB_FORMAT_RGB565:
- colour_data[0] = rgb565[val & 0xffff];
- colour_data[1] = rgb565[val >> 16];
- write_mask = LFB_WRITE_COLOUR;
- count = 2;
- break;
- case LFB_FORMAT_RGB555:
- colour_data[0] = argb1555[val & 0xffff];
- colour_data[1] = argb1555[val >> 16];
- write_mask = LFB_WRITE_COLOUR;
- count = 2;
- break;
- case LFB_FORMAT_ARGB1555:
- colour_data[0] = argb1555[val & 0xffff];
- alpha_data[0] = colour_data[0].a;
- colour_data[1] = argb1555[val >> 16];
- alpha_data[1] = colour_data[1].a;
- write_mask = LFB_WRITE_COLOUR;
- count = 2;
- break;
-
- case LFB_FORMAT_ARGB8888:
- colour_data[0].b = val & 0xff;
- colour_data[0].g = (val >> 8) & 0xff;
- colour_data[0].r = (val >> 16) & 0xff;
- alpha_data[0] = (val >> 24) & 0xff;
- write_mask = LFB_WRITE_COLOUR;
- addr >>= 1;
- break;
-
- case LFB_FORMAT_DEPTH:
- depth_data[0] = val;
- depth_data[1] = val >> 16;
- write_mask = LFB_WRITE_DEPTH;
- count = 2;
- break;
-
- default:
- fatal("voodoo_fb_writel : bad LFB format %08X\n", voodoo->lfbMode);
- }
-
- x = addr & 0x7fe;
- y = (addr >> 11) & 0x3ff;
-
- if (SLI_ENABLED)
- {
- if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) ||
- ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1)))
- return;
- y >>= 1;
- }
-
- if (voodoo->fb_write_offset == voodoo->params.front_offset)
- voodoo->dirty_line[y] = 1;
-
- write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width);
- write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width);
-
-// pclog("fb_writel %08x x=%i y=%i rw=%i %08x wo=%08x\n", addr, x, y, voodoo->row_width, write_addr, voodoo->fb_write_offset);
-
- if (voodoo->lfbMode & 0x100)
- {
- int c;
-
- for (c = 0; c < count; c++)
- {
- rgba8_t write_data = colour_data[c];
- uint16_t new_depth = depth_data[c];
-
- if (params->fbzMode & FBZ_DEPTH_ENABLE)
- {
- uint16_t old_depth = *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]);
-
- DEPTH_TEST(new_depth);
- }
-
- if ((params->fbzMode & FBZ_CHROMAKEY) &&
- write_data.r == params->chromaKey_r &&
- write_data.g == params->chromaKey_g &&
- write_data.b == params->chromaKey_b)
- goto skip_pixel;
-
- if (params->fogMode & FOG_ENABLE)
- {
- int32_t z = new_depth << 12;
- int64_t w_depth = new_depth;
- int32_t ia = alpha_data[c] << 12;
-
- APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth);
- }
-
- if (params->alphaMode & 1)
- ALPHA_TEST(alpha_data[c]);
-
- if (params->alphaMode & (1 << 4))
- {
- uint16_t dat = *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]);
- int dest_r, dest_g, dest_b, dest_a;
-
- dest_r = (dat >> 8) & 0xf8;
- dest_g = (dat >> 3) & 0xfc;
- dest_b = (dat << 3) & 0xf8;
- dest_r |= (dest_r >> 5);
- dest_g |= (dest_g >> 6);
- dest_b |= (dest_b >> 5);
- dest_a = 0xff;
-
- ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data[c]);
- }
-
- if (params->fbzMode & FBZ_RGB_WMASK)
- *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, (x >> 1) + c, y);
- if (params->fbzMode & FBZ_DEPTH_WMASK)
- *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth;
-
-skip_pixel:
- write_addr += 2;
- write_addr_aux += 2;
- }
- }
- else
- {
- int c;
-
- for (c = 0; c < count; c++)
- {
- if (write_mask & LFB_WRITE_COLOUR)
- *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y);
- if (write_mask & LFB_WRITE_DEPTH)
- *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data[c];
-
- write_addr += 2;
- write_addr_aux += 2;
- }
- }
-}
-
-static void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p)
-{
- int lod, s, t;
- voodoo_t *voodoo = (voodoo_t *)p;
- int tmu;
-
- if (addr & 0x400000)
- return; /*TREX != 0*/
-
- tmu = (addr & 0x200000) ? 1 : 0;
-
- if (tmu && !voodoo->dual_tmus)
- return;
-
-// pclog("voodoo_tex_writel : %08X %08X %i\n", addr, val, voodoo->params.tformat);
-
- lod = (addr >> 17) & 0xf;
- t = (addr >> 9) & 0xff;
- if (voodoo->params.tformat[tmu] & 8)
- s = (addr >> 1) & 0xfe;
- else
- {
- if (voodoo->params.textureMode[tmu] & (1 << 31))
- s = addr & 0xfc;
- else
- s = (addr >> 1) & 0xfc;
- }
-
- if (lod > LOD_MAX)
- return;
-
-// if (addr >= 0x200000)
-// return;
-
- if (voodoo->params.tformat[tmu] & 8)
- addr = voodoo->params.tex_base[tmu][lod] + s*2 + (t << voodoo->params.tex_shift[tmu][lod])*2;
- else
- addr = voodoo->params.tex_base[tmu][lod] + s + (t << voodoo->params.tex_shift[tmu][lod]);
- if (voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT])
- {
-// pclog("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT);
- flush_texture_cache(voodoo, addr & voodoo->texture_mask, tmu);
- }
- *(uint32_t *)(&voodoo->tex_mem[tmu][addr & voodoo->texture_mask]) = val;
-}
-
-#define WAKE_DELAY (TIMER_USEC * 100)
-static inline void wake_fifo_thread(voodoo_t *voodoo)
-{
- if (!timer_is_enabled(&voodoo->wake_timer))
- {
- /*Don't wake FIFO thread immediately - if we do that it will probably
- process one word and go back to sleep, requiring it to be woken on
- almost every write. Instead, wait a short while so that the CPU
- emulation writes more data so we have more batched-up work.*/
- timer_set_delay_u64(&voodoo->wake_timer, WAKE_DELAY);
- }
-}
-
-static inline void wake_fifo_thread_now(voodoo_t *voodoo)
-{
- thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
-}
-
-static void voodoo_wake_timer(void *p)
-{
- voodoo_t *voodoo = (voodoo_t *)p;
-
- thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
-}
-
-static inline void queue_command(voodoo_t *voodoo, uint32_t addr_type, uint32_t val)
-{
- fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_write_idx & FIFO_MASK];
-
- while (FIFO_FULL)
- {
- thread_reset_event(voodoo->fifo_not_full_event);
- if (FIFO_FULL)
- {
- thread_wait_event(voodoo->fifo_not_full_event, 1); /*Wait for room in ringbuffer*/
- if (FIFO_FULL)
- wake_fifo_thread_now(voodoo);
- }
- }
-
- fifo->val = val;
- fifo->addr_type = addr_type;
-
- voodoo->fifo_write_idx++;
-
- if (FIFO_ENTRIES > 0xe000)
- wake_fifo_thread(voodoo);
-}
static uint16_t voodoo_readw(uint32_t addr, void *p)
{
@@ -5939,10 +133,10 @@ static uint16_t voodoo_readw(uint32_t addr, void *p)
voodoo->flush = 1;
while (!FIFO_EMPTY)
{
- wake_fifo_thread_now(voodoo);
+ voodoo_wake_fifo_thread_now(voodoo);
thread_wait_event(voodoo->fifo_not_full_event, 1);
}
- wait_for_render_thread_idle(voodoo);
+ voodoo_wait_for_render_thread_idle(voodoo);
voodoo->flush = 0;
return voodoo_fb_readw(addr, voodoo);
@@ -5951,24 +145,6 @@ static uint16_t voodoo_readw(uint32_t addr, void *p)
return 0xffff;
}
-static void voodoo_flush(voodoo_t *voodoo)
-{
- voodoo->flush = 1;
- while (!FIFO_EMPTY)
- {
- wake_fifo_thread_now(voodoo);
- thread_wait_event(voodoo->fifo_not_full_event, 1);
- }
- wait_for_render_thread_idle(voodoo);
- voodoo->flush = 0;
-}
-
-static void wake_fifo_threads(voodoo_set_t *set, voodoo_t *voodoo)
-{
- wake_fifo_thread(voodoo);
- if (SLI_ENABLED && voodoo->type != VOODOO_2 && set->voodoos[0] == voodoo)
- wake_fifo_thread(set->voodoos[1]);
-}
static uint32_t voodoo_readl(uint32_t addr, void *p)
{
@@ -5999,10 +175,10 @@ static uint32_t voodoo_readl(uint32_t addr, void *p)
voodoo->flush = 1;
while (!FIFO_EMPTY)
{
- wake_fifo_thread_now(voodoo);
+ voodoo_wake_fifo_thread_now(voodoo);
thread_wait_event(voodoo->fifo_not_full_event, 1);
}
- wait_for_render_thread_idle(voodoo);
+ voodoo_wait_for_render_thread_idle(voodoo);
voodoo->flush = 0;
temp = voodoo_fb_readl(addr, voodoo);
@@ -6029,7 +205,7 @@ static uint32_t voodoo_readl(uint32_t addr, void *p)
(voodoo_other->cmdfifo_depth_rd != voodoo_other->cmdfifo_depth_wr))
busy = 1;
if (!voodoo_other->voodoo_busy)
- wake_fifo_thread(voodoo_other);
+ voodoo_wake_fifo_thread(voodoo_other);
}
fifo_size = 0xffff - fifo_entries;
@@ -6049,7 +225,7 @@ static uint32_t voodoo_readl(uint32_t addr, void *p)
temp |= 0x380; /*Busy*/
if (!voodoo->voodoo_busy)
- wake_fifo_thread(voodoo);
+ voodoo_wake_fifo_thread(voodoo);
}
break;
@@ -6178,7 +354,7 @@ static uint32_t voodoo_readl(uint32_t addr, void *p)
break;
default:
- fatal("voodoo_readl : bad addr %08X\n", addr);
+ pclog("voodoo_readl : bad addr %08X\n", addr);
temp = 0xffffffff;
}
@@ -6190,39 +366,11 @@ static void voodoo_writew(uint32_t addr, uint16_t val, void *p)
voodoo_t *voodoo = (voodoo_t *)p;
voodoo->wr_count++;
addr &= 0xffffff;
-
- if (addr == voodoo->last_write_addr+4)
- cycles -= voodoo->burst_time;
- else
- cycles -= voodoo->write_time;
- voodoo->last_write_addr = addr;
+
+ cycles -= voodoo->write_time;
if ((addr & 0xc00000) == 0x400000) /*Framebuffer*/
- queue_command(voodoo, addr | FIFO_WRITEW_FB, val);
-}
-
-static void voodoo_pixelclock_update(voodoo_t *voodoo)
-{
- int m = (voodoo->dac_pll_regs[0] & 0x7f) + 2;
- int n1 = ((voodoo->dac_pll_regs[0] >> 8) & 0x1f) + 2;
- int n2 = ((voodoo->dac_pll_regs[0] >> 13) & 0x07);
- float t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2);
- double clock_const;
- int line_length;
-
- if ((voodoo->dac_data[6] & 0xf0) == 0x20 ||
- (voodoo->dac_data[6] & 0xf0) == 0x60 ||
- (voodoo->dac_data[6] & 0xf0) == 0x70)
- t /= 2.0f;
-
- line_length = (voodoo->hSync & 0xff) + ((voodoo->hSync >> 16) & 0x3ff);
-
-// pclog("Pixel clock %f MHz hsync %08x line_length %d\n", t, voodoo->hSync, line_length);
-
- voodoo->pixel_clock = t;
-
- clock_const = cpuclock / t;
- voodoo->line_time = (uint64_t)((double)line_length * clock_const * (double)(1ull << 32));
+ voodoo_queue_command(voodoo, addr | FIFO_WRITEW_FB, val);
}
static void voodoo_writel(uint32_t addr, uint32_t val, void *p)
@@ -6242,11 +390,11 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p)
if (addr & 0x800000) /*Texture*/
{
voodoo->tex_count++;
- queue_command(voodoo, addr | FIFO_WRITEL_TEX, val);
+ voodoo_queue_command(voodoo, addr | FIFO_WRITEL_TEX, val);
}
else if (addr & 0x400000) /*Framebuffer*/
{
- queue_command(voodoo, addr | FIFO_WRITEL_FB, val);
+ voodoo_queue_command(voodoo, addr | FIFO_WRITEL_FB, val);
}
else if ((addr & 0x200000) && (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE))
{
@@ -6254,7 +402,7 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p)
*(uint32_t *)&voodoo->fb_mem[(voodoo->cmdfifo_base + (addr & 0x3fffc)) & voodoo->fb_mask] = val;
voodoo->cmdfifo_depth_wr++;
if ((voodoo->cmdfifo_depth_wr - voodoo->cmdfifo_depth_rd) < 20)
- wake_fifo_thread(voodoo);
+ voodoo_wake_fifo_thread(voodoo);
}
else switch (addr & 0x3fc)
{
@@ -6268,44 +416,46 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p)
case SST_swapbufferCMD:
voodoo->cmd_written++;
+ thread_lock_mutex(voodoo->swap_mutex);
voodoo->swap_count++;
+ thread_unlock_mutex(voodoo->swap_mutex);
if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)
return;
- queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
+ voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
if (!voodoo->voodoo_busy)
- wake_fifo_threads(voodoo->set, voodoo);
+ voodoo_wake_fifo_threads(voodoo->set, voodoo);
break;
case SST_triangleCMD:
if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)
return;
voodoo->cmd_written++;
- queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
+ voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
if (!voodoo->voodoo_busy)
- wake_fifo_threads(voodoo->set, voodoo);
+ voodoo_wake_fifo_threads(voodoo->set, voodoo);
break;
case SST_ftriangleCMD:
if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)
return;
voodoo->cmd_written++;
- queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
+ voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
if (!voodoo->voodoo_busy)
- wake_fifo_threads(voodoo->set, voodoo);
+ voodoo_wake_fifo_threads(voodoo->set, voodoo);
break;
case SST_fastfillCMD:
if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)
return;
voodoo->cmd_written++;
- queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
+ voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
if (!voodoo->voodoo_busy)
- wake_fifo_threads(voodoo->set, voodoo);
+ voodoo_wake_fifo_threads(voodoo->set, voodoo);
break;
case SST_nopCMD:
if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)
return;
voodoo->cmd_written++;
- queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
+ voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
if (!voodoo->voodoo_busy)
- wake_fifo_threads(voodoo->set, voodoo);
+ voodoo_wake_fifo_threads(voodoo->set, voodoo);
break;
case SST_fbiInit4:
@@ -6349,7 +499,9 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p)
if ((voodoo->fbiInit1 & FBIINIT1_VIDEO_RESET) && !(val & FBIINIT1_VIDEO_RESET))
{
voodoo->line = 0;
+ thread_lock_mutex(voodoo->swap_mutex);
voodoo->swap_count = 0;
+ thread_unlock_mutex(voodoo->swap_mutex);
voodoo->retrace_count = 0;
}
voodoo->fbiInit1 = (val & ~5) | (voodoo->fbiInit1 & 5);
@@ -6457,7 +609,10 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p)
break;
case SST_fbiInit7:
if (voodoo->initEnable & 0x01)
+ {
voodoo->fbiInit7 = val;
+ voodoo->cmdfifo_enabled = val & 0x100;
+ }
break;
case SST_cmdFifoBaseAddr:
@@ -6487,7 +642,7 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p)
}
else
{
- queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
+ voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
}
break;
}
@@ -6521,274 +676,6 @@ static void voodoo_snoop_writel(uint32_t addr, uint32_t val, void *p)
voodoo_writel(addr, val, set->voodoos[1]);
}
-static uint32_t cmdfifo_get(voodoo_t *voodoo)
-{
- uint32_t val;
-
- while (voodoo->cmdfifo_depth_rd == voodoo->cmdfifo_depth_wr)
- {
- thread_wait_event(voodoo->wake_fifo_thread, -1);
- thread_reset_event(voodoo->wake_fifo_thread);
- }
-
- val = *(uint32_t *)&voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask];
-
- voodoo->cmdfifo_depth_rd++;
- voodoo->cmdfifo_rp += 4;
-
-// pclog(" CMDFIFO get %08x\n", val);
- return val;
-}
-
-static inline float cmdfifo_get_f(voodoo_t *voodoo)
-{
- union
- {
- uint32_t i;
- float f;
- } tempif;
-
- tempif.i = cmdfifo_get(voodoo);
- return tempif.f;
-}
-
-enum
-{
- CMDFIFO3_PC_MASK_RGB = (1 << 10),
- CMDFIFO3_PC_MASK_ALPHA = (1 << 11),
- CMDFIFO3_PC_MASK_Z = (1 << 12),
- CMDFIFO3_PC_MASK_Wb = (1 << 13),
- CMDFIFO3_PC_MASK_W0 = (1 << 14),
- CMDFIFO3_PC_MASK_S0_T0 = (1 << 15),
- CMDFIFO3_PC_MASK_W1 = (1 << 16),
- CMDFIFO3_PC_MASK_S1_T1 = (1 << 17),
-
- CMDFIFO3_PC = (1 << 28)
-};
-
-static void fifo_thread(void *param)
-{
- voodoo_t *voodoo = (voodoo_t *)param;
-
- while (1)
- {
- thread_set_event(voodoo->fifo_not_full_event);
- thread_wait_event(voodoo->wake_fifo_thread, -1);
- thread_reset_event(voodoo->wake_fifo_thread);
- voodoo->voodoo_busy = 1;
- while (!FIFO_EMPTY)
- {
- uint64_t start_time = timer_read();
- uint64_t end_time;
- fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
-
- switch (fifo->addr_type & FIFO_TYPE)
- {
- case FIFO_WRITEL_REG:
- voodoo_reg_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
- break;
- case FIFO_WRITEW_FB:
- wait_for_render_thread_idle(voodoo);
- voodoo_fb_writew(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
- break;
- case FIFO_WRITEL_FB:
- wait_for_render_thread_idle(voodoo);
- voodoo_fb_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
- break;
- case FIFO_WRITEL_TEX:
- if (!(fifo->addr_type & 0x400000))
- voodoo_tex_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
- break;
- }
- voodoo->fifo_read_idx++;
- fifo->addr_type = FIFO_INVALID;
-
- if (FIFO_ENTRIES > 0xe000)
- thread_set_event(voodoo->fifo_not_full_event);
-
- end_time = timer_read();
- voodoo->time += end_time - start_time;
- }
-
- while (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr)
- {
- uint64_t start_time = timer_read();
- uint64_t end_time;
- uint32_t header = cmdfifo_get(voodoo);
- uint32_t addr;
- uint32_t mask;
- int smode;
- int num;
- int num_verticies;
- int v_num;
-
-// pclog(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp);
-
- switch (header & 7)
- {
- case 0:
-// pclog("CMDFIFO0\n");
- switch ((header >> 3) & 7)
- {
- case 0: /*NOP*/
- break;
-
- case 3: /*JMP local frame buffer*/
- voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc;
-// pclog("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header);
- break;
-
- default:
- fatal("Bad CMDFIFO0 %08x\n", header);
- }
- break;
-
- case 1:
- num = header >> 16;
- addr = (header & 0x7ff8) >> 1;
-// pclog("CMDFIFO1 addr=%08x\n",addr);
- while (num--)
- {
- uint32_t val = cmdfifo_get(voodoo);
- if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD ||
- (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD)
- voodoo->cmd_written_fifo++;
-
- voodoo_reg_writel(addr, val, voodoo);
-
- if (header & (1 << 15))
- addr += 4;
- }
- break;
-
- case 3:
- num = (header >> 29) & 7;
- mask = header;//(header >> 10) & 0xff;
- smode = (header >> 22) & 0xf;
- voodoo_reg_writel(SST_sSetupMode, ((header >> 10) & 0xff) | (smode << 16), voodoo);
- num_verticies = (header >> 6) & 0xf;
- v_num = 0;
- if (((header >> 3) & 7) == 2)
- v_num = 1;
-// pclog("CMDFIFO3: num=%i verts=%i mask=%02x\n", num, num_verticies, (header >> 10) & 0xff);
-// pclog("CMDFIFO3 %02x %i\n", (header >> 10), (header >> 3) & 7);
-
- while (num_verticies--)
- {
- voodoo->verts[3].sVx = cmdfifo_get_f(voodoo);
- voodoo->verts[3].sVy = cmdfifo_get_f(voodoo);
- if (mask & CMDFIFO3_PC_MASK_RGB)
- {
- if (header & CMDFIFO3_PC)
- {
- uint32_t val = cmdfifo_get(voodoo);
- voodoo->verts[3].sBlue = (float)(val & 0xff);
- voodoo->verts[3].sGreen = (float)((val >> 8) & 0xff);
- voodoo->verts[3].sRed = (float)((val >> 16) & 0xff);
- voodoo->verts[3].sAlpha = (float)((val >> 24) & 0xff);
- }
- else
- {
- voodoo->verts[3].sRed = cmdfifo_get_f(voodoo);
- voodoo->verts[3].sGreen = cmdfifo_get_f(voodoo);
- voodoo->verts[3].sBlue = cmdfifo_get_f(voodoo);
- }
- }
- if ((mask & CMDFIFO3_PC_MASK_ALPHA) && !(header & CMDFIFO3_PC))
- voodoo->verts[3].sAlpha = cmdfifo_get_f(voodoo);
- if (mask & CMDFIFO3_PC_MASK_Z)
- voodoo->verts[3].sVz = cmdfifo_get_f(voodoo);
- if (mask & CMDFIFO3_PC_MASK_Wb)
- voodoo->verts[3].sWb = cmdfifo_get_f(voodoo);
- if (mask & CMDFIFO3_PC_MASK_W0)
- voodoo->verts[3].sW0 = cmdfifo_get_f(voodoo);
- if (mask & CMDFIFO3_PC_MASK_S0_T0)
- {
- voodoo->verts[3].sS0 = cmdfifo_get_f(voodoo);
- voodoo->verts[3].sT0 = cmdfifo_get_f(voodoo);
- }
- if (mask & CMDFIFO3_PC_MASK_W1)
- voodoo->verts[3].sW1 = cmdfifo_get_f(voodoo);
- if (mask & CMDFIFO3_PC_MASK_S1_T1)
- {
- voodoo->verts[3].sS1 = cmdfifo_get_f(voodoo);
- voodoo->verts[3].sT1 = cmdfifo_get_f(voodoo);
- }
- if (v_num)
- voodoo_reg_writel(SST_sDrawTriCMD, 0, voodoo);
- else
- voodoo_reg_writel(SST_sBeginTriCMD, 0, voodoo);
- v_num++;
- if (v_num == 3 && ((header >> 3) & 7) == 0)
- v_num = 0;
- }
- break;
-
- case 4:
- num = (header >> 29) & 7;
- mask = (header >> 15) & 0x3fff;
- addr = (header & 0x7ff8) >> 1;
-// pclog("CMDFIFO4 addr=%08x\n",addr);
- while (mask)
- {
- if (mask & 1)
- {
- uint32_t val = cmdfifo_get(voodoo);
- if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD ||
- (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD)
- voodoo->cmd_written_fifo++;
-
- voodoo_reg_writel(addr, val, voodoo);
- }
-
- addr += 4;
- mask >>= 1;
- }
- while (num--)
- cmdfifo_get(voodoo);
- break;
-
- case 5:
- if (header & 0x3fc0000)
- fatal("CMDFIFO packet 5 has byte disables set %08x\n", header);
- num = (header >> 3) & 0x7ffff;
- addr = cmdfifo_get(voodoo) & 0xffffff;
-// pclog("CMDFIFO5 addr=%08x num=%i\n", addr, num);
- switch (header >> 30)
- {
- case 2: /*Framebuffer*/
- while (num--)
- {
- uint32_t val = cmdfifo_get(voodoo);
- voodoo_fb_writel(addr, val, voodoo);
- addr += 4;
- }
- break;
- case 3: /*Texture*/
- while (num--)
- {
- uint32_t val = cmdfifo_get(voodoo);
- voodoo_tex_writel(addr, val, voodoo);
- addr += 4;
- }
- break;
-
- default:
- fatal("CMDFIFO packet 5 bad space %08x %08x\n", header, voodoo->cmdfifo_rp);
- }
- break;
-
- default:
- pclog("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp);
- }
-
- end_time = timer_read();
- voodoo->time += end_time - start_time;
- }
- voodoo->voodoo_busy = 0;
- }
-}
-
static void voodoo_recalcmapping(voodoo_set_t *set)
{
if (set->nr_cards == 2)
@@ -6935,529 +822,6 @@ void voodoo_pci_write(int func, int addr, uint8_t val, void *p)
}
}
-static void voodoo_calc_clutData(voodoo_t *voodoo)
-{
- int c;
-
- for (c = 0; c < 256; c++)
- {
- voodoo->clutData256[c].r = (voodoo->clutData[c >> 3].r*(8-(c & 7)) +
- voodoo->clutData[(c >> 3)+1].r*(c & 7)) >> 3;
- voodoo->clutData256[c].g = (voodoo->clutData[c >> 3].g*(8-(c & 7)) +
- voodoo->clutData[(c >> 3)+1].g*(c & 7)) >> 3;
- voodoo->clutData256[c].b = (voodoo->clutData[c >> 3].b*(8-(c & 7)) +
- voodoo->clutData[(c >> 3)+1].b*(c & 7)) >> 3;
- }
-
- for (c = 0; c < 65536; c++)
- {
- int r = (c >> 8) & 0xf8;
- int g = (c >> 3) & 0xfc;
- int b = (c << 3) & 0xf8;
-// r |= (r >> 5);
-// g |= (g >> 6);
-// b |= (b >> 5);
-
- voodoo->video_16to32[c] = (voodoo->clutData256[r].r << 16) | (voodoo->clutData256[g].g << 8) | voodoo->clutData256[b].b;
- }
-}
-
-
-
-#define FILTDIV 256
-
-static int FILTCAP, FILTCAPG, FILTCAPB = 0; /* color filter threshold values */
-
-static void voodoo_generate_filter_v1(voodoo_t *voodoo)
-{
- int g, h;
- float difference, diffg, diffb;
- float thiscol, thiscolg, thiscolb, lined;
- float fcr, fcg, fcb;
-
- fcr = FILTCAP * 5;
- fcg = FILTCAPG * 6;
- fcb = FILTCAPB * 5;
-
- for (g=0;g FILTCAP)
- difference = FILTCAP;
- if (difference < -FILTCAP)
- difference = -FILTCAP;
-
- if (diffg > FILTCAPG)
- diffg = FILTCAPG;
- if (diffg < -FILTCAPG)
- diffg = -FILTCAPG;
-
- if (diffb > FILTCAPB)
- diffb = FILTCAPB;
- if (diffb < -FILTCAPB)
- diffb = -FILTCAPB;
-
- // hack - to make it not bleed onto black
- //if (g == 0){
- //difference = diffg = diffb = 0;
- //}
-
- if ((difference < fcr) || (-difference > -fcr))
- thiscol = g + (difference / 2);
- if ((diffg < fcg) || (-diffg > -fcg))
- thiscolg = g + (diffg / 2); /* need these divides so we can actually undither! */
- if ((diffb < fcb) || (-diffb > -fcb))
- thiscolb = g + (diffb / 2);
-
- if (thiscol < 0)
- thiscol = 0;
- if (thiscol > FILTDIV-1)
- thiscol = FILTDIV-1;
-
- if (thiscolg < 0)
- thiscolg = 0;
- if (thiscolg > FILTDIV-1)
- thiscolg = FILTDIV-1;
-
- if (thiscolb < 0)
- thiscolb = 0;
- if (thiscolb > FILTDIV-1)
- thiscolb = FILTDIV-1;
-
- voodoo->thefilter[g][h] = thiscol;
- voodoo->thefilterg[g][h] = thiscolg;
- voodoo->thefilterb[g][h] = thiscolb;
- }
-
- lined = g + 4;
- if (lined > 255)
- lined = 255;
- voodoo->purpleline[g][0] = lined;
- voodoo->purpleline[g][2] = lined;
-
- lined = g + 0;
- if (lined > 255)
- lined = 255;
- voodoo->purpleline[g][1] = lined;
- }
-}
-
-static void voodoo_generate_filter_v2(voodoo_t *voodoo)
-{
- int g, h;
- float difference;
- float thiscol, thiscolg, thiscolb, lined;
- float clr, clg, clb = 0;
- float fcr, fcg, fcb = 0;
-
- // pre-clamping
-
- fcr = FILTCAP;
- fcg = FILTCAPG;
- fcb = FILTCAPB;
-
- if (fcr > 32) fcr = 32;
- if (fcg > 32) fcg = 32;
- if (fcb > 32) fcb = 32;
-
- for (g=0;g<256;g++) // pixel 1 - our target pixel we want to bleed into
- {
- for (h=0;h<256;h++) // pixel 2 - our main pixel
- {
- float avg;
- float avgdiff;
-
- difference = (float)(g - h);
- avg = (float)((g + g + g + g + h) / 5);
- avgdiff = avg - (float)((g + h + h + h + h) / 5);
- if (avgdiff < 0) avgdiff *= -1;
- if (difference < 0) difference *= -1;
-
- thiscol = thiscolg = thiscolb = g;
-
- // try lighten
- if (h > g)
- {
- clr = clg = clb = avgdiff;
-
- if (clr>fcr) clr=fcr;
- if (clg>fcg) clg=fcg;
- if (clb>fcb) clb=fcb;
-
-
- thiscol = g + clr;
- thiscolg = g + clg;
- thiscolb = g + clb;
-
- if (thiscol>g+FILTCAP)
- thiscol=g+FILTCAP;
- if (thiscolg>g+FILTCAPG)
- thiscolg=g+FILTCAPG;
- if (thiscolb>g+FILTCAPB)
- thiscolb=g+FILTCAPB;
-
-
- if (thiscol>g+avgdiff)
- thiscol=g+avgdiff;
- if (thiscolg>g+avgdiff)
- thiscolg=g+avgdiff;
- if (thiscolb>g+avgdiff)
- thiscolb=g+avgdiff;
-
- }
-
- if (difference > FILTCAP)
- thiscol = g;
- if (difference > FILTCAPG)
- thiscolg = g;
- if (difference > FILTCAPB)
- thiscolb = g;
-
- // clamp
- if (thiscol < 0) thiscol = 0;
- if (thiscolg < 0) thiscolg = 0;
- if (thiscolb < 0) thiscolb = 0;
-
- if (thiscol > 255) thiscol = 255;
- if (thiscolg > 255) thiscolg = 255;
- if (thiscolb > 255) thiscolb = 255;
-
- // add to the table
- voodoo->thefilter[g][h] = (thiscol);
- voodoo->thefilterg[g][h] = (thiscolg);
- voodoo->thefilterb[g][h] = (thiscolb);
-
- // debug the ones that don't give us much of a difference
- //if (difference < FILTCAP)
- //pclog("Voodoofilter: %ix%i - %f difference, %f average difference, R=%f, G=%f, B=%f\n", g, h, difference, avgdiff, thiscol, thiscolg, thiscolb);
- }
-
- lined = g + 3;
- if (lined > 255)
- lined = 255;
- voodoo->purpleline[g][0] = lined;
- voodoo->purpleline[g][1] = 0;
- voodoo->purpleline[g][2] = lined;
- }
-}
-
-static void voodoo_threshold_check(voodoo_t *voodoo)
-{
- int r, g, b;
-
- if (!voodoo->scrfilterEnabled)
- return; /* considered disabled; don't check and generate */
-
- /* Check for changes, to generate anew table */
- if (voodoo->scrfilterThreshold != voodoo->scrfilterThresholdOld)
- {
- r = (voodoo->scrfilterThreshold >> 16) & 0xFF;
- g = (voodoo->scrfilterThreshold >> 8 ) & 0xFF;
- b = voodoo->scrfilterThreshold & 0xFF;
-
- FILTCAP = r;
- FILTCAPG = g;
- FILTCAPB = b;
-
- pclog("Voodoo Filter Threshold Check: %06x - RED %i GREEN %i BLUE %i\n", voodoo->scrfilterThreshold, r, g, b);
-
- voodoo->scrfilterThresholdOld = voodoo->scrfilterThreshold;
-
- if (voodoo->type == VOODOO_2)
- voodoo_generate_filter_v2(voodoo);
- else
- voodoo_generate_filter_v1(voodoo);
- }
-}
-
-static void voodoo_filterline_v1(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line)
-{
- int x;
-
- // Scratchpad for avoiding feedback streaks
- uint8_t fil3[(voodoo->h_disp) * 3];
-
- /* 16 to 32-bit */
- for (x=0; x> 5) & 63) << 2);
- fil[x*3+2] = (((src[x] >> 11) & 31) << 3);
-
- // Copy to our scratchpads
- fil3[x*3+0] = fil[x*3+0];
- fil3[x*3+1] = fil[x*3+1];
- fil3[x*3+2] = fil[x*3+2];
- }
-
-
- /* lines */
-
- if (line & 1)
- {
- for (x=0; xpurpleline[fil[x*3]][0];
- fil[x*3+1] = voodoo->purpleline[fil[x*3+1]][1];
- fil[x*3+2] = voodoo->purpleline[fil[x*3+2]][2];
- }
- }
-
-
- /* filtering time */
-
- for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]];
- fil3[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]];
- fil3[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]];
- }
-
- for (x=1; xthefilterb[fil3[x*3]][fil3[ (x-1) *3]];
- fil[(x)*3+1] = voodoo->thefilterg[fil3[x*3+1]][fil3[ (x-1) *3+1]];
- fil[(x)*3+2] = voodoo->thefilter[fil3[x*3+2]][fil3[ (x-1) *3+2]];
- }
-
- for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]];
- fil3[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]];
- fil3[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]];
- }
-
- for (x=0; xthefilterb[fil3[x*3]][fil3[ (x+1) *3]];
- fil[(x)*3+1] = voodoo->thefilterg[fil3[x*3+1]][fil3[ (x+1) *3+1]];
- fil[(x)*3+2] = voodoo->thefilter[fil3[x*3+2]][fil3[ (x+1) *3+2]];
- }
-}
-
-
-static void voodoo_filterline_v2(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line)
-{
- int x;
-
- // Scratchpad for blending filter
- uint8_t fil3[(voodoo->h_disp) * 3];
-
- /* 16 to 32-bit */
- for (x=0; x> 5) & 63) << 2);
- fil3[x*3+2] = fil[x*3+2] = (((src[x] >> 11) & 31) << 3);
- }
-
- /* filtering time */
-
- for (x=1; xthefilterb [((src[x+3] & 31) << 3)] [((src[x] & 31) << 3)];
- fil3[(x+3)*3+1] = voodoo->thefilterg [(((src[x+3] >> 5) & 63) << 2)] [(((src[x] >> 5) & 63) << 2)];
- fil3[(x+3)*3+2] = voodoo->thefilter [(((src[x+3] >> 11) & 31) << 3)] [(((src[x] >> 11) & 31) << 3)];
-
- fil[(x+2)*3] = voodoo->thefilterb [fil3[(x+2)*3]][((src[x] & 31) << 3)];
- fil[(x+2)*3+1] = voodoo->thefilterg [fil3[(x+2)*3+1]][(((src[x] >> 5) & 63) << 2)];
- fil[(x+2)*3+2] = voodoo->thefilter [fil3[(x+2)*3+2]][(((src[x] >> 11) & 31) << 3)];
-
- fil3[(x+1)*3] = voodoo->thefilterb [fil[(x+1)*3]][((src[x] & 31) << 3)];
- fil3[(x+1)*3+1] = voodoo->thefilterg [fil[(x+1)*3+1]][(((src[x] >> 5) & 63) << 2)];
- fil3[(x+1)*3+2] = voodoo->thefilter [fil[(x+1)*3+2]][(((src[x] >> 11) & 31) << 3)];
-
- fil[(x-1)*3] = voodoo->thefilterb [fil3[(x-1)*3]][((src[x] & 31) << 3)];
- fil[(x-1)*3+1] = voodoo->thefilterg [fil3[(x-1)*3+1]][(((src[x] >> 5) & 63) << 2)];
- fil[(x-1)*3+2] = voodoo->thefilter [fil3[(x-1)*3+2]][(((src[x] >> 11) & 31) << 3)];
- }
-
- // unroll for edge cases
-
- fil3[(column-3)*3] = voodoo->thefilterb [((src[column-3] & 31) << 3)] [((src[column] & 31) << 3)];
- fil3[(column-3)*3+1] = voodoo->thefilterg [(((src[column-3] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)];
- fil3[(column-3)*3+2] = voodoo->thefilter [(((src[column-3] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)];
-
- fil3[(column-2)*3] = voodoo->thefilterb [((src[column-2] & 31) << 3)] [((src[column] & 31) << 3)];
- fil3[(column-2)*3+1] = voodoo->thefilterg [(((src[column-2] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)];
- fil3[(column-2)*3+2] = voodoo->thefilter [(((src[column-2] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)];
-
- fil3[(column-1)*3] = voodoo->thefilterb [((src[column-1] & 31) << 3)] [((src[column] & 31) << 3)];
- fil3[(column-1)*3+1] = voodoo->thefilterg [(((src[column-1] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)];
- fil3[(column-1)*3+2] = voodoo->thefilter [(((src[column-1] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)];
-
- fil[(column-2)*3] = voodoo->thefilterb [fil3[(column-2)*3]][((src[column] & 31) << 3)];
- fil[(column-2)*3+1] = voodoo->thefilterg [fil3[(column-2)*3+1]][(((src[column] >> 5) & 63) << 2)];
- fil[(column-2)*3+2] = voodoo->thefilter [fil3[(column-2)*3+2]][(((src[column] >> 11) & 31) << 3)];
-
- fil[(column-1)*3] = voodoo->thefilterb [fil3[(column-1)*3]][((src[column] & 31) << 3)];
- fil[(column-1)*3+1] = voodoo->thefilterg [fil3[(column-1)*3+1]][(((src[column] >> 5) & 63) << 2)];
- fil[(column-1)*3+2] = voodoo->thefilter [fil3[(column-1)*3+2]][(((src[column] >> 11) & 31) << 3)];
-
- fil3[(column-1)*3] = voodoo->thefilterb [fil[(column-1)*3]][((src[column] & 31) << 3)];
- fil3[(column-1)*3+1] = voodoo->thefilterg [fil[(column-1)*3+1]][(((src[column] >> 5) & 63) << 2)];
- fil3[(column-1)*3+2] = voodoo->thefilter [fil[(column-1)*3+2]][(((src[column] >> 11) & 31) << 3)];
-}
-
-void voodoo_callback(void *p)
-{
- voodoo_t *voodoo = (voodoo_t *)p;
-
- if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS)
- {
- if (voodoo->line < voodoo->v_disp)
- {
- voodoo_t *draw_voodoo;
- int draw_line;
-
- if (SLI_ENABLED)
- {
- if (voodoo == voodoo->set->voodoos[1])
- goto skip_draw;
-
- if (((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) ? 1 : 0) == (voodoo->line & 1))
- draw_voodoo = voodoo;
- else
- draw_voodoo = voodoo->set->voodoos[1];
- draw_line = voodoo->line >> 1;
- }
- else
- {
- if (!(voodoo->fbiInit0 & 1))
- goto skip_draw;
- draw_voodoo = voodoo;
- draw_line = voodoo->line;
- }
-
- if (draw_voodoo->dirty_line[draw_line])
- {
- uint32_t *p = &((uint32_t *)buffer32->line[voodoo->line])[32];
- uint16_t *src = (uint16_t *)&draw_voodoo->fb_mem[draw_voodoo->front_offset + draw_line*draw_voodoo->row_width];
- int x;
-
- draw_voodoo->dirty_line[draw_line] = 0;
-
- if (voodoo->line < voodoo->dirty_line_low)
- {
- voodoo->dirty_line_low = voodoo->line;
- video_wait_for_buffer();
- }
- if (voodoo->line > voodoo->dirty_line_high)
- voodoo->dirty_line_high = voodoo->line;
-
- if (voodoo->scrfilter && voodoo->scrfilterEnabled)
- {
- uint8_t fil[(voodoo->h_disp) * 3]; /* interleaved 24-bit RGB */
-
- if (voodoo->type == VOODOO_2)
- voodoo_filterline_v2(voodoo, fil, voodoo->h_disp, src, voodoo->line);
- else
- voodoo_filterline_v1(voodoo, fil, voodoo->h_disp, src, voodoo->line);
-
- for (x = 0; x < voodoo->h_disp; x++)
- {
- p[x] = (voodoo->clutData256[fil[x*3]].b << 0 | voodoo->clutData256[fil[x*3+1]].g << 8 | voodoo->clutData256[fil[x*3+2]].r << 16);
- }
- }
- else
- {
- for (x = 0; x < voodoo->h_disp; x++)
- {
- p[x] = draw_voodoo->video_16to32[src[x]];
- }
- }
- }
- }
- }
-skip_draw:
- if (voodoo->line == voodoo->v_disp)
- {
-// pclog("retrace %i %i %08x %i\n", voodoo->retrace_count, voodoo->swap_interval, voodoo->swap_offset, voodoo->swap_pending);
- voodoo->retrace_count++;
- if (SLI_ENABLED && (voodoo->fbiInit2 & FBIINIT2_SWAP_ALGORITHM_MASK) == FBIINIT2_SWAP_ALGORITHM_SLI_SYNC)
- {
- if (voodoo == voodoo->set->voodoos[0])
- {
- voodoo_t *voodoo_1 = voodoo->set->voodoos[1];
-
- /*Only swap if both Voodoos are waiting for buffer swap*/
- if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval) &&
- voodoo_1->swap_pending && (voodoo_1->retrace_count > voodoo_1->swap_interval))
- {
- memset(voodoo->dirty_line, 1, 1024);
- voodoo->retrace_count = 0;
- voodoo->front_offset = voodoo->swap_offset;
- if (voodoo->swap_count > 0)
- voodoo->swap_count--;
- voodoo->swap_pending = 0;
-
- memset(voodoo_1->dirty_line, 1, 1024);
- voodoo_1->retrace_count = 0;
- voodoo_1->front_offset = voodoo_1->swap_offset;
- if (voodoo_1->swap_count > 0)
- voodoo_1->swap_count--;
- voodoo_1->swap_pending = 0;
-
- thread_set_event(voodoo->wake_fifo_thread);
- thread_set_event(voodoo_1->wake_fifo_thread);
-
- voodoo->frame_count++;
- voodoo_1->frame_count++;
- }
- }
- }
- else
- {
- if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval))
- {
- memset(voodoo->dirty_line, 1, 1024);
- voodoo->retrace_count = 0;
- voodoo->front_offset = voodoo->swap_offset;
- if (voodoo->swap_count > 0)
- voodoo->swap_count--;
- voodoo->swap_pending = 0;
- thread_set_event(voodoo->wake_fifo_thread);
- voodoo->frame_count++;
- }
- }
- voodoo->v_retrace = 1;
- }
- voodoo->line++;
-
- if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS)
- {
- if (voodoo->line == voodoo->v_disp)
- {
- if (voodoo->dirty_line_high > voodoo->dirty_line_low)
- svga_doblit(0, voodoo->v_disp, voodoo->h_disp, voodoo->v_disp-1, voodoo->svga);
- if (voodoo->clutData_dirty)
- {
- voodoo->clutData_dirty = 0;
- voodoo_calc_clutData(voodoo);
- }
- voodoo->dirty_line_high = -1;
- voodoo->dirty_line_low = 2000;
- }
- }
-
- if (voodoo->line >= voodoo->v_total)
- {
- voodoo->line = 0;
- voodoo->v_retrace = 0;
- }
- if (voodoo->line_time)
- timer_advance_u64(&voodoo->timer, voodoo->line_time);
- else
- timer_advance_u64(&voodoo->timer, TIMER_USEC * 32);
-}
static void voodoo_add_status_info(char *s, int max_len, void *p)
{
@@ -7465,37 +829,38 @@ static void voodoo_add_status_info(char *s, int max_len, void *p)
voodoo_t *voodoo = voodoo_set->voodoos[0];
voodoo_t *voodoo_slave = voodoo_set->voodoos[1];
char temps[512], temps2[256];
- int pixel_count_current[2];
+ int pixel_count_current[4];
int pixel_count_total;
- int texel_count_current[2];
+ int texel_count_current[4];
int texel_count_total;
- int render_time[2];
+ int render_time[4];
uint64_t new_time = timer_read();
uint64_t status_diff = new_time - status_time;
status_time = new_time;
+ int c;
if (!status_diff)
status_diff = 1;
- svga_add_status_info(s, max_len, &voodoo->svga);
-
- pixel_count_current[0] = voodoo->pixel_count[0];
- pixel_count_current[1] = voodoo->pixel_count[1];
- texel_count_current[0] = voodoo->texel_count[0];
- texel_count_current[1] = voodoo->texel_count[1];
- render_time[0] = voodoo->render_time[0];
- render_time[1] = voodoo->render_time[1];
+ for (c = 0; c < 4; c++)
+ {
+ pixel_count_current[c] = voodoo->pixel_count[c];
+ texel_count_current[c] = voodoo->texel_count[c];
+ render_time[c] = voodoo->render_time[c];
+ }
if (voodoo_set->nr_cards == 2)
{
- pixel_count_current[0] += voodoo_slave->pixel_count[0];
- pixel_count_current[1] += voodoo_slave->pixel_count[1];
- texel_count_current[0] += voodoo_slave->texel_count[0];
- texel_count_current[1] += voodoo_slave->texel_count[1];
- render_time[0] = (render_time[0] + voodoo_slave->render_time[0]) / 2;
- render_time[1] = (render_time[1] + voodoo_slave->render_time[1]) / 2;
+ for (c = 0; c < 4; c++)
+ {
+ pixel_count_current[c] += voodoo_slave->pixel_count[c];
+ texel_count_current[c] += voodoo_slave->texel_count[c];
+ render_time[c] = (render_time[c] + voodoo_slave->render_time[c]) / 2;
+ }
}
- pixel_count_total = (pixel_count_current[0] + pixel_count_current[1]) - (voodoo->pixel_count_old[0] + voodoo->pixel_count_old[1]);
- texel_count_total = (texel_count_current[0] + texel_count_current[1]) - (voodoo->texel_count_old[0] + voodoo->texel_count_old[1]);
+ pixel_count_total = (pixel_count_current[0] + pixel_count_current[1] + pixel_count_current[2] + pixel_count_current[3]) -
+ (voodoo->pixel_count_old[0] + voodoo->pixel_count_old[1] + voodoo->pixel_count_old[2] + voodoo->pixel_count_old[3]);
+ texel_count_total = (texel_count_current[0] + texel_count_current[1] + texel_count_current[2] + texel_count_current[3]) -
+ (voodoo->texel_count_old[0] + voodoo->texel_count_old[1] + voodoo->texel_count_old[2] + voodoo->texel_count_old[3]);
sprintf(temps, "%f Mpixels/sec (%f)\n%f Mtexels/sec (%f)\n%f ktris/sec\n%f%% CPU (%f%% real)\n%d frames/sec (%i)\n%f%% CPU (%f%% real)\n"/*%d reads/sec\n%d write/sec\n%d tex/sec\n*/,
(double)pixel_count_total/1000000.0,
((double)pixel_count_total/1000000.0) / ((double)render_time[0] / status_diff),
@@ -7503,45 +868,61 @@ static void voodoo_add_status_info(char *s, int max_len, void *p)
((double)texel_count_total/1000000.0) / ((double)render_time[0] / status_diff),
(double)voodoo->tri_count/1000.0, ((double)voodoo->time * 100.0) / timer_freq, ((double)voodoo->time * 100.0) / status_diff, voodoo->frame_count, voodoo_recomp,
((double)voodoo->render_time[0] * 100.0) / timer_freq, ((double)voodoo->render_time[0] * 100.0) / status_diff);
- if (voodoo->render_threads == 2)
+ if (voodoo->render_threads >= 2)
{
sprintf(temps2, "%f%% CPU (%f%% real)\n",
((double)voodoo->render_time[1] * 100.0) / timer_freq, ((double)voodoo->render_time[1] * 100.0) / status_diff);
strncat(temps, temps2, sizeof(temps)-1);
}
+ if (voodoo->render_threads == 4)
+ {
+ sprintf(temps2, "%f%% CPU (%f%% real)\n%f%% CPU (%f%% real)\n",
+ ((double)voodoo->render_time[2] * 100.0) / timer_freq, ((double)voodoo->render_time[2] * 100.0) / status_diff,
+ ((double)voodoo->render_time[3] * 100.0) / timer_freq, ((double)voodoo->render_time[3] * 100.0) / status_diff);
+ strncat(temps, temps2, sizeof(temps)-1);
+ }
if (voodoo_set->nr_cards == 2)
{
sprintf(temps2, "%f%% CPU (%f%% real)\n",
((double)voodoo_slave->render_time[0] * 100.0) / timer_freq, ((double)voodoo_slave->render_time[0] * 100.0) / status_diff);
strncat(temps, temps2, sizeof(temps)-1);
- if (voodoo_slave->render_threads == 2)
+ if (voodoo_slave->render_threads >= 2)
{
sprintf(temps2, "%f%% CPU (%f%% real)\n",
((double)voodoo_slave->render_time[1] * 100.0) / timer_freq, ((double)voodoo_slave->render_time[1] * 100.0) / status_diff);
strncat(temps, temps2, sizeof(temps)-1);
}
+ if (voodoo_slave->render_threads == 4)
+ {
+ sprintf(temps2, "%f%% CPU (%f%% real)\n%f%% CPU (%f%% real)\n",
+ ((double)voodoo_slave->render_time[2] * 100.0) / timer_freq, ((double)voodoo_slave->render_time[2] * 100.0) / status_diff,
+ ((double)voodoo_slave->render_time[3] * 100.0) / timer_freq, ((double)voodoo_slave->render_time[3] * 100.0) / status_diff);
+ strncat(temps, temps2, sizeof(temps)-1);
+ }
}
strncat(s, temps, max_len);
- voodoo->pixel_count_old[0] = pixel_count_current[0];
- voodoo->pixel_count_old[1] = pixel_count_current[1];
- voodoo->texel_count_old[0] = texel_count_current[0];
- voodoo->texel_count_old[1] = texel_count_current[1];
+ for (c = 0; c < 4; c++)
+ {
+ voodoo->pixel_count_old[c] = pixel_count_current[c];
+ voodoo->texel_count_old[c] = texel_count_current[c];
+ voodoo->render_time[c] = 0;
+ }
voodoo->tri_count = voodoo->frame_count = 0;
voodoo->rd_count = voodoo->wr_count = voodoo->tex_count = 0;
voodoo->time = 0;
- voodoo->render_time[0] = voodoo->render_time[1] = 0;
if (voodoo_set->nr_cards == 2)
{
- voodoo_slave->pixel_count_old[0] = pixel_count_current[0];
- voodoo_slave->pixel_count_old[1] = pixel_count_current[1];
- voodoo_slave->texel_count_old[0] = texel_count_current[0];
- voodoo_slave->texel_count_old[1] = texel_count_current[1];
+ for (c = 0; c < 4; c++)
+ {
+ voodoo_slave->pixel_count_old[c] = pixel_count_current[c];
+ voodoo_slave->texel_count_old[c] = texel_count_current[c];
+ voodoo_slave->render_time[c] = 0;
+ }
voodoo_slave->tri_count = voodoo_slave->frame_count = 0;
voodoo_slave->rd_count = voodoo_slave->wr_count = voodoo_slave->tex_count = 0;
voodoo_slave->time = 0;
- voodoo_slave->render_time[0] = voodoo_slave->render_time[1] = 0;
}
voodoo_recomp = 0;
}
@@ -7571,6 +952,7 @@ void *voodoo_card_init()
memset(voodoo, 0, sizeof(voodoo_t));
voodoo->bilinear_enabled = device_get_config_int("bilinear");
+ voodoo->dithersub_enabled = device_get_config_int("dithersub");
voodoo->scrfilter = device_get_config_int("dacfilter");
voodoo->texture_size = device_get_config_int("texture_memory");
voodoo->texture_mask = (voodoo->texture_size << 20) - 1;
@@ -7632,15 +1014,24 @@ void *voodoo_card_init()
voodoo->wake_fifo_thread = thread_create_event();
voodoo->wake_render_thread[0] = thread_create_event();
voodoo->wake_render_thread[1] = thread_create_event();
+ voodoo->wake_render_thread[2] = thread_create_event();
+ voodoo->wake_render_thread[3] = thread_create_event();
voodoo->wake_main_thread = thread_create_event();
voodoo->fifo_not_full_event = thread_create_event();
voodoo->render_not_full_event[0] = thread_create_event();
voodoo->render_not_full_event[1] = thread_create_event();
- voodoo->fifo_thread = thread_create(fifo_thread, voodoo);
- voodoo->render_thread[0] = thread_create(render_thread_1, voodoo);
- if (voodoo->render_threads == 2)
- voodoo->render_thread[1] = thread_create(render_thread_2, voodoo);
-
+ voodoo->render_not_full_event[2] = thread_create_event();
+ voodoo->render_not_full_event[3] = thread_create_event();
+ voodoo->fifo_thread = thread_create(voodoo_fifo_thread, voodoo);
+ voodoo->render_thread[0] = thread_create(voodoo_render_thread_1, voodoo);
+ if (voodoo->render_threads >= 2)
+ voodoo->render_thread[1] = thread_create(voodoo_render_thread_2, voodoo);
+ if (voodoo->render_threads == 4)
+ {
+ voodoo->render_thread[2] = thread_create(voodoo_render_thread_3, voodoo);
+ voodoo->render_thread[3] = thread_create(voodoo_render_thread_4, voodoo);
+ }
+ voodoo->swap_mutex = thread_create_mutex();
timer_add(&voodoo->wake_timer, voodoo_wake_timer, (void *)voodoo, 0);
for (c = 0; c < 0x100; c++)
@@ -7701,6 +1092,125 @@ void *voodoo_card_init()
return voodoo;
}
+void *voodoo_2d3d_card_init(int type)
+{
+ int c;
+ voodoo_t *voodoo = malloc(sizeof(voodoo_t));
+ memset(voodoo, 0, sizeof(voodoo_t));
+
+ voodoo->bilinear_enabled = device_get_config_int("bilinear");
+ voodoo->dithersub_enabled = device_get_config_int("dithersub");
+ voodoo->scrfilter = device_get_config_int("dacfilter");
+ voodoo->render_threads = device_get_config_int("render_threads");
+
+ voodoo->odd_even_mask = voodoo->render_threads - 1;
+#ifndef NO_CODEGEN
+ voodoo->use_recompiler = device_get_config_int("recompiler");
+#endif
+ voodoo->type = type;
+ voodoo->dual_tmus = (type == VOODOO_3) ? 1 : 0;
+
+ /*generate filter lookup tables*/
+ voodoo_generate_filter_v2(voodoo);
+
+ for (c = 0; c < TEX_CACHE_MAX; c++)
+ {
+ voodoo->texture_cache[0][c].data = malloc((256*256 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) * 4);
+ voodoo->texture_cache[0][c].base = -1; /*invalid*/
+ voodoo->texture_cache[0][c].refcount = 0;
+ if (voodoo->dual_tmus)
+ {
+ voodoo->texture_cache[1][c].data = malloc((256*256 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) * 4);
+ voodoo->texture_cache[1][c].base = -1; /*invalid*/
+ voodoo->texture_cache[1][c].refcount = 0;
+ }
+ }
+
+ timer_add(&voodoo->timer, voodoo_callback, voodoo, 1);
+
+ voodoo->fbiInit0 = 0;
+
+ voodoo->wake_fifo_thread = thread_create_event();
+ voodoo->wake_render_thread[0] = thread_create_event();
+ voodoo->wake_render_thread[1] = thread_create_event();
+ voodoo->wake_render_thread[2] = thread_create_event();
+ voodoo->wake_render_thread[3] = thread_create_event();
+ voodoo->wake_main_thread = thread_create_event();
+ voodoo->fifo_not_full_event = thread_create_event();
+ voodoo->render_not_full_event[0] = thread_create_event();
+ voodoo->render_not_full_event[1] = thread_create_event();
+ voodoo->render_not_full_event[2] = thread_create_event();
+ voodoo->render_not_full_event[3] = thread_create_event();
+ voodoo->fifo_thread = thread_create(voodoo_fifo_thread, voodoo);
+ voodoo->render_thread[0] = thread_create(voodoo_render_thread_1, voodoo);
+ if (voodoo->render_threads >= 2)
+ voodoo->render_thread[1] = thread_create(voodoo_render_thread_2, voodoo);
+ if (voodoo->render_threads == 4)
+ {
+ voodoo->render_thread[2] = thread_create(voodoo_render_thread_3, voodoo);
+ voodoo->render_thread[3] = thread_create(voodoo_render_thread_4, voodoo);
+ }
+ voodoo->swap_mutex = thread_create_mutex();
+ timer_add(&voodoo->wake_timer, voodoo_wake_timer, (void *)voodoo, 0);
+
+ for (c = 0; c < 0x100; c++)
+ {
+ rgb332[c].r = c & 0xe0;
+ rgb332[c].g = (c << 3) & 0xe0;
+ rgb332[c].b = (c << 6) & 0xc0;
+ rgb332[c].r = rgb332[c].r | (rgb332[c].r >> 3) | (rgb332[c].r >> 6);
+ rgb332[c].g = rgb332[c].g | (rgb332[c].g >> 3) | (rgb332[c].g >> 6);
+ rgb332[c].b = rgb332[c].b | (rgb332[c].b >> 2);
+ rgb332[c].b = rgb332[c].b | (rgb332[c].b >> 4);
+ rgb332[c].a = 0xff;
+
+ ai44[c].a = (c & 0xf0) | ((c & 0xf0) >> 4);
+ ai44[c].r = (c & 0x0f) | ((c & 0x0f) << 4);
+ ai44[c].g = ai44[c].b = ai44[c].r;
+ }
+
+ for (c = 0; c < 0x10000; c++)
+ {
+ rgb565[c].r = (c >> 8) & 0xf8;
+ rgb565[c].g = (c >> 3) & 0xfc;
+ rgb565[c].b = (c << 3) & 0xf8;
+ rgb565[c].r |= (rgb565[c].r >> 5);
+ rgb565[c].g |= (rgb565[c].g >> 6);
+ rgb565[c].b |= (rgb565[c].b >> 5);
+ rgb565[c].a = 0xff;
+
+ argb1555[c].r = (c >> 7) & 0xf8;
+ argb1555[c].g = (c >> 2) & 0xf8;
+ argb1555[c].b = (c << 3) & 0xf8;
+ argb1555[c].r |= (argb1555[c].r >> 5);
+ argb1555[c].g |= (argb1555[c].g >> 5);
+ argb1555[c].b |= (argb1555[c].b >> 5);
+ argb1555[c].a = (c & 0x8000) ? 0xff : 0;
+
+ argb4444[c].a = (c >> 8) & 0xf0;
+ argb4444[c].r = (c >> 4) & 0xf0;
+ argb4444[c].g = c & 0xf0;
+ argb4444[c].b = (c << 4) & 0xf0;
+ argb4444[c].a |= (argb4444[c].a >> 4);
+ argb4444[c].r |= (argb4444[c].r >> 4);
+ argb4444[c].g |= (argb4444[c].g >> 4);
+ argb4444[c].b |= (argb4444[c].b >> 4);
+
+ ai88[c].a = (c >> 8);
+ ai88[c].r = c & 0xff;
+ ai88[c].g = c & 0xff;
+ ai88[c].b = c & 0xff;
+ }
+#ifndef NO_CODEGEN
+ voodoo_codegen_init(voodoo);
+#endif
+
+ voodoo->disp_buffer = 0;
+ voodoo->draw_buffer = 1;
+
+ return voodoo;
+}
+
void *voodoo_init()
{
voodoo_set_t *voodoo_set = malloc(sizeof(voodoo_set_t));
@@ -7767,21 +1277,29 @@ void voodoo_card_close(voodoo_t *voodoo)
int c;
#ifndef RELEASE_BUILD
- f = romfopen("texram.dmp", "wb");
- fwrite(voodoo->tex_mem[0], voodoo->texture_size*1024*1024, 1, f);
- fclose(f);
- if (voodoo->dual_tmus)
+ if (voodoo->tex_mem[0])
{
- f = romfopen("texram2.dmp", "wb");
- fwrite(voodoo->tex_mem[1], voodoo->texture_size*1024*1024, 1, f);
+ f = romfopen("texram.dmp", "wb");
+ fwrite(voodoo->tex_mem[0], voodoo->texture_size*1024*1024, 1, f);
fclose(f);
+ if (voodoo->dual_tmus)
+ {
+ f = romfopen("texram2.dmp", "wb");
+ fwrite(voodoo->tex_mem[1], voodoo->texture_size*1024*1024, 1, f);
+ fclose(f);
+ }
}
#endif
thread_kill(voodoo->fifo_thread);
thread_kill(voodoo->render_thread[0]);
- if (voodoo->render_threads == 2)
+ if (voodoo->render_threads >= 2)
thread_kill(voodoo->render_thread[1]);
+ if (voodoo->render_threads == 4)
+ {
+ thread_kill(voodoo->render_thread[2]);
+ thread_kill(voodoo->render_thread[3]);
+ }
thread_destroy_event(voodoo->fifo_not_full_event);
thread_destroy_event(voodoo->wake_main_thread);
thread_destroy_event(voodoo->wake_fifo_thread);
@@ -7799,10 +1317,13 @@ void voodoo_card_close(voodoo_t *voodoo)
#ifndef NO_CODEGEN
voodoo_codegen_close(voodoo);
#endif
- free(voodoo->fb_mem);
- if (voodoo->dual_tmus)
- free(voodoo->tex_mem[1]);
- free(voodoo->tex_mem[0]);
+ if (voodoo->type < VOODOO_BANSHEE && voodoo->fb_mem)
+ {
+ free(voodoo->fb_mem);
+ if (voodoo->dual_tmus)
+ free(voodoo->tex_mem[1]);
+ free(voodoo->tex_mem[0]);
+ }
free(voodoo);
}
@@ -7889,6 +1410,12 @@ static device_config_t voodoo_config[] =
.type = CONFIG_BINARY,
.default_int = 1
},
+ {
+ .name = "dithersub",
+ .description = "Dither subtraction",
+ .type = CONFIG_BINARY,
+ .default_int = 1
+ },
{
.name = "dacfilter",
.description = "Screen Filter",
@@ -7909,6 +1436,10 @@ static device_config_t voodoo_config[] =
.description = "2",
.value = 2
},
+ {
+ .description = "4",
+ .value = 4
+ },
{
.description = ""
}
diff --git a/src/vid_voodoo_banshee.c b/src/vid_voodoo_banshee.c
new file mode 100644
index 0000000..cf676a0
--- /dev/null
+++ b/src/vid_voodoo_banshee.c
@@ -0,0 +1,2900 @@
+#include
+#include "ibm.h"
+#include "device.h"
+#include "io.h"
+#include "mem.h"
+#include "pci.h"
+#include "rom.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_ddc.h"
+#include "vid_svga.h"
+#include "vid_svga_render.h"
+#include "vid_voodoo_banshee.h"
+#include "vid_voodoo_common.h"
+#include "vid_voodoo_display.h"
+#include "vid_voodoo_fifo.h"
+#include "vid_voodoo_regs.h"
+#include "vid_voodoo_render.h"
+#include "x86.h"
+
+#ifdef CLAMP
+#undef CLAMP
+#endif
+
+static uint8_t vb_filter_v1_rb[256][256];
+static uint8_t vb_filter_v1_g [256][256];
+
+static uint8_t vb_filter_bx_rb[256][256];
+static uint8_t vb_filter_bx_g [256][256];
+
+enum
+{
+ TYPE_BANSHEE = 0,
+ TYPE_V3_2000,
+ TYPE_V3_3000
+};
+
+typedef struct banshee_t
+{
+ svga_t svga;
+
+ rom_t bios_rom;
+
+ uint8_t pci_regs[256];
+
+ uint32_t memBaseAddr0;
+ uint32_t memBaseAddr1;
+ uint32_t ioBaseAddr;
+
+ uint32_t agpInit0;
+ uint32_t dramInit0, dramInit1;
+ uint32_t lfbMemoryConfig;
+ uint32_t miscInit0, miscInit1;
+ uint32_t pciInit0;
+ uint32_t vgaInit0, vgaInit1;
+
+ uint32_t command_2d;
+ uint32_t srcBaseAddr_2d;
+
+ uint32_t pllCtrl0, pllCtrl1, pllCtrl2;
+
+ uint32_t dacMode;
+ int dacAddr;
+
+ uint32_t vidDesktopOverlayStride;
+ uint32_t vidDesktopStartAddr;
+ uint32_t vidProcCfg;
+ uint32_t vidScreenSize;
+ uint32_t vidSerialParallelPort;
+
+ int overlay_pix_fmt;
+
+ uint32_t hwCurPatAddr, hwCurLoc, hwCurC0, hwCurC1;
+
+ uint32_t intrCtrl;
+
+ uint32_t overlay_buffer[2][4096];
+
+ mem_mapping_t linear_mapping;
+
+ mem_mapping_t reg_mapping_low; /*0000000-07fffff*/
+ mem_mapping_t reg_mapping_high; /*0c00000-1ffffff - Windows 2000 puts the BIOS ROM in between these two areas*/
+
+ voodoo_t *voodoo;
+
+ uint32_t desktop_addr;
+ int desktop_y;
+ uint32_t desktop_stride_tiled;
+
+ int type;
+} banshee_t;
+
+enum
+{
+ Init_status = 0x00,
+ Init_pciInit0 = 0x04,
+ Init_lfbMemoryConfig = 0x0c,
+ Init_miscInit0 = 0x10,
+ Init_miscInit1 = 0x14,
+ Init_dramInit0 = 0x18,
+ Init_dramInit1 = 0x1c,
+ Init_agpInit0 = 0x20,
+ Init_vgaInit0 = 0x28,
+ Init_vgaInit1 = 0x2c,
+ Init_2dCommand = 0x30,
+ Init_2dSrcBaseAddr = 0x34,
+ Init_strapInfo = 0x38,
+
+ PLL_pllCtrl0 = 0x40,
+ PLL_pllCtrl1 = 0x44,
+ PLL_pllCtrl2 = 0x48,
+
+ DAC_dacMode = 0x4c,
+ DAC_dacAddr = 0x50,
+ DAC_dacData = 0x54,
+
+ Video_vidProcCfg = 0x5c,
+ Video_maxRgbDelta = 0x58,
+ Video_hwCurPatAddr = 0x60,
+ Video_hwCurLoc = 0x64,
+ Video_hwCurC0 = 0x68,
+ Video_hwCurC1 = 0x6c,
+ Video_vidSerialParallelPort = 0x78,
+ Video_vidScreenSize = 0x98,
+ Video_vidOverlayStartCoords = 0x9c,
+ Video_vidOverlayEndScreenCoords = 0xa0,
+ Video_vidOverlayDudx = 0xa4,
+ Video_vidOverlayDudxOffsetSrcWidth = 0xa8,
+ Video_vidOverlayDvdy = 0xac,
+ Video_vidOverlayDvdyOffset = 0xe0,
+ Video_vidDesktopStartAddr = 0xe4,
+ Video_vidDesktopOverlayStride = 0xe8
+};
+
+enum
+{
+ cmdBaseAddr0 = 0x20,
+ cmdBaseSize0 = 0x24,
+ cmdBump0 = 0x28,
+ cmdRdPtrL0 = 0x2c,
+ cmdRdPtrH0 = 0x30,
+ cmdAMin0 = 0x34,
+ cmdAMax0 = 0x3c,
+ cmdFifoDepth0 = 0x44,
+ cmdHoleCnt0 = 0x48
+};
+
+#define VGAINIT0_EXTENDED_SHIFT_OUT (1 << 12)
+
+#define VIDPROCCFG_VIDPROC_ENABLE (1 << 0)
+#define VIDPROCCFG_CURSOR_MODE (1 << 1)
+#define VIDPROCCFG_HALF_MODE (1 << 4)
+#define VIDPROCCFG_OVERLAY_ENABLE (1 << 8)
+#define VIDPROCCFG_OVERLAY_CLUT_BYPASS (1 << 11)
+#define VIDPROCCFG_OVERLAY_CLUT_SEL (1 << 13)
+#define VIDPROCCFG_H_SCALE_ENABLE (1 << 14)
+#define VIDPROCCFG_V_SCALE_ENABLE (1 << 15)
+#define VIDPROCCFG_FILTER_MODE_MASK (3 << 16)
+#define VIDPROCCFG_FILTER_MODE_POINT (0 << 16)
+#define VIDPROCCFG_FILTER_MODE_DITHER_2X2 (1 << 16)
+#define VIDPROCCFG_FILTER_MODE_DITHER_4X4 (2 << 16)
+#define VIDPROCCFG_FILTER_MODE_BILINEAR (3 << 16)
+#define VIDPROCCFG_DESKTOP_PIX_FORMAT ((banshee->vidProcCfg >> 18) & 7)
+#define VIDPROCCFG_OVERLAY_PIX_FORMAT ((banshee->vidProcCfg >> 21) & 7)
+#define VIDPROCCFG_OVERLAY_PIX_FORMAT_SHIFT (21)
+#define VIDPROCCFG_OVERLAY_PIX_FORMAT_MASK (7 << VIDPROCCFG_OVERLAY_PIX_FORMAT_SHIFT)
+#define VIDPROCCFG_DESKTOP_TILE (1 << 24)
+#define VIDPROCCFG_OVERLAY_TILE (1 << 25)
+#define VIDPROCCFG_2X_MODE (1 << 26)
+#define VIDPROCCFG_HWCURSOR_ENA (1 << 27)
+
+#define OVERLAY_FMT_565 (1)
+#define OVERLAY_FMT_YUYV422 (5)
+#define OVERLAY_FMT_UYVY422 (6)
+#define OVERLAY_FMT_565_DITHER (7)
+
+#define OVERLAY_START_X_MASK (0xfff)
+#define OVERLAY_START_Y_SHIFT (12)
+#define OVERLAY_START_Y_MASK (0xfff << OVERLAY_START_Y_SHIFT)
+
+#define OVERLAY_END_X_MASK (0xfff)
+#define OVERLAY_END_Y_SHIFT (12)
+#define OVERLAY_END_Y_MASK (0xfff << OVERLAY_END_Y_SHIFT)
+
+#define OVERLAY_SRC_WIDTH_SHIFT (19)
+#define OVERLAY_SRC_WIDTH_MASK (0x1fff << OVERLAY_SRC_WIDTH_SHIFT)
+
+#define VID_STRIDE_OVERLAY_SHIFT (16)
+#define VID_STRIDE_OVERLAY_MASK (0x7fff << VID_STRIDE_OVERLAY_SHIFT)
+
+#define VID_DUDX_MASK (0xffffff)
+#define VID_DVDY_MASK (0xffffff)
+
+#define PIX_FORMAT_8 0
+#define PIX_FORMAT_RGB565 1
+#define PIX_FORMAT_RGB24 2
+#define PIX_FORMAT_RGB32 3
+
+#define VIDSERIAL_DDC_DCK_W (1 << 19)
+#define VIDSERIAL_DDC_DDA_W (1 << 20)
+#define VIDSERIAL_DDC_DCK_R (1 << 21)
+#define VIDSERIAL_DDC_DDA_R (1 << 22)
+#define VIDSERIAL_I2C_SCK_W (1 << 24)
+#define VIDSERIAL_I2C_SDA_W (1 << 25)
+#define VIDSERIAL_I2C_SCK_R (1 << 26)
+#define VIDSERIAL_I2C_SDA_R (1 << 27)
+
+#define MISCINIT0_Y_ORIGIN_SWAP_SHIFT (18)
+#define MISCINIT0_Y_ORIGIN_SWAP_MASK (0xfff << MISCINIT0_Y_ORIGIN_SWAP_SHIFT)
+
+static uint32_t banshee_status(banshee_t *banshee);
+
+static void banshee_out(uint16_t addr, uint8_t val, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ svga_t *svga = &banshee->svga;
+ uint8_t old;
+
+// /*if (addr != 0x3c9) */pclog("banshee_out : %04X %02X %04X:%04X\n", addr, val, CS,cpu_state.pc);
+
+ if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
+ addr ^= 0x60;
+
+ switch (addr)
+ {
+ case 0x3D4:
+ svga->crtcreg = val & 0x3f;
+ 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 (old != val)
+ {
+ if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
+ {
+ svga->fullchange = changeframecount;
+ svga_recalctimings(svga);
+ }
+ }
+ break;
+ }
+ svga_out(addr, val, svga);
+}
+
+static uint8_t banshee_in(uint16_t addr, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ svga_t *svga = &banshee->svga;
+ uint8_t temp;
+
+// if (addr != 0x3da) pclog("banshee_in : %04X ", addr);
+
+ if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
+ addr ^= 0x60;
+
+ switch (addr)
+ {
+ case 0x3c2:
+ if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x40)
+ temp = 0;
+ else
+ temp = 0x10;
+ break;
+ case 0x3D4:
+ temp = svga->crtcreg;
+ break;
+ case 0x3D5:
+ temp = svga->crtc[svga->crtcreg];
+ break;
+ default:
+ temp = svga_in(addr, svga);
+ break;
+ }
+// if (addr != 0x3da) pclog("%02X %04X:%04X %i\n", temp, CS,cpu_state.pc, ins);
+ return temp;
+}
+
+static void banshee_updatemapping(banshee_t *banshee)
+{
+ svga_t *svga = &banshee->svga;
+
+ if (!(banshee->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))
+ {
+// pclog("Update mapping - PCI disabled\n");
+ mem_mapping_disable(&svga->mapping);
+ mem_mapping_disable(&banshee->linear_mapping);
+ mem_mapping_disable(&banshee->reg_mapping_low);
+ mem_mapping_disable(&banshee->reg_mapping_high);
+ return;
+ }
+
+ pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc);
+ switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/
+ {
+ 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;
+ }
+
+ pclog("Linear framebuffer %08X ", banshee->memBaseAddr1);
+ mem_mapping_set_addr(&banshee->linear_mapping, banshee->memBaseAddr1, 32 << 20);
+ pclog("registers %08X\n", banshee->memBaseAddr0);
+ mem_mapping_set_addr(&banshee->reg_mapping_low, banshee->memBaseAddr0, 8 << 20);
+ mem_mapping_set_addr(&banshee->reg_mapping_high, banshee->memBaseAddr0 + 0xc00000, 20 << 20);
+}
+
+static void banshee_render_16bpp_tiled(svga_t *svga)
+{
+ banshee_t *banshee = (banshee_t *)svga->p;
+ int x;
+ int offset = 32;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+ uint32_t addr;
+ int drawn = 0;
+
+ if (banshee->vidProcCfg & VIDPROCCFG_HALF_MODE)
+ addr = banshee->desktop_addr + ((banshee->desktop_y >> 1) & 31) * 128 + ((banshee->desktop_y >> 6) * banshee->desktop_stride_tiled);
+ else
+ addr = banshee->desktop_addr + (banshee->desktop_y & 31) * 128 + ((banshee->desktop_y >> 5) * banshee->desktop_stride_tiled);
+
+ for (x = 0; x <= svga->hdisp; x += 64)
+ {
+ if (svga->hwcursor_on || svga->overlay_on)
+ svga->changedvram[addr >> 12] = 2;
+ if (svga->changedvram[addr >> 12] || svga->fullchange)
+ {
+ uint16_t *vram_p = (uint16_t *)&svga->vram[addr & svga->vram_display_mask];
+ int xx;
+
+ for (xx = 0; xx < 64; xx++)
+ *p++ = video_16to32[*vram_p++];
+
+ drawn = 1;
+ }
+ else
+ p += 64;
+ addr += 128*32;
+ }
+
+ if (drawn)
+ {
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+ }
+
+ banshee->desktop_y++;
+}
+
+static void banshee_recalctimings(svga_t *svga)
+{
+ banshee_t *banshee = (banshee_t *)svga->p;
+ voodoo_t *voodoo = banshee->voodoo;
+
+/*7 R/W Horizontal Retrace End bit 5. -
+ 6 R/W Horizontal Retrace Start bit 8 0x4
+ 5 R/W Horizontal Blank End bit 6. -
+ 4 R/W Horizontal Blank Start bit 8. 0x3
+ 3 R/W Reserved. -
+ 2 R/W Horizontal Display Enable End bit 8. 0x1
+ 1 R/W Reserved. -
+ 0 R/W Horizontal Total bit 8. 0x0*/
+ if (svga->crtc[0x1a] & 0x01) svga->htotal += 0x100;
+ if (svga->crtc[0x1a] & 0x04) svga->hdisp += 0x100;
+/*6 R/W Vertical Retrace Start bit 10 0x10
+ 5 R/W Reserved. -
+ 4 R/W Vertical Blank Start bit 10. 0x15
+ 3 R/W Reserved. -
+ 2 R/W Vertical Display Enable End bit 10 0x12
+ 1 R/W Reserved. -
+ 0 R/W Vertical Total bit 10. 0x6*/
+ if (svga->crtc[0x1b] & 0x01) svga->vtotal += 0x400;
+ if (svga->crtc[0x1b] & 0x04) svga->dispend += 0x400;
+ if (svga->crtc[0x1b] & 0x10) svga->vblankstart += 0x400;
+ if (svga->crtc[0x1b] & 0x40) svga->vsyncstart += 0x400;
+// pclog("svga->hdisp=%i\n", svga->hdisp);
+
+ if (banshee->vgaInit0 & VGAINIT0_EXTENDED_SHIFT_OUT)
+ {
+ switch (VIDPROCCFG_DESKTOP_PIX_FORMAT)
+ {
+ case PIX_FORMAT_8:
+ svga->render = svga_render_8bpp_highres;
+ svga->bpp = 8;
+ break;
+ case PIX_FORMAT_RGB565:
+ svga->render = (banshee->vidProcCfg & VIDPROCCFG_DESKTOP_TILE) ? banshee_render_16bpp_tiled : svga_render_16bpp_highres;
+ svga->bpp = 16;
+ break;
+ case PIX_FORMAT_RGB24:
+ svga->render = svga_render_24bpp_highres;
+ svga->bpp = 24;
+ break;
+ case PIX_FORMAT_RGB32:
+ svga->render = svga_render_32bpp_highres;
+ svga->bpp = 32;
+ break;
+
+#ifndef RELEASE_BUILD
+ default:
+ fatal("Unknown pixel format %08x\n", banshee->vgaInit0);
+#endif
+ }
+ svga->rowcount = 0;
+ if (!(banshee->vidProcCfg & VIDPROCCFG_DESKTOP_TILE) && (banshee->vidProcCfg & VIDPROCCFG_HALF_MODE))
+ svga->linedbl = 1;
+ else
+ svga->linedbl = 0;
+ if (banshee->vidProcCfg & VIDPROCCFG_DESKTOP_TILE)
+ svga->rowoffset = ((banshee->vidDesktopOverlayStride & 0x3fff) * 128) >> 3;
+ else
+ svga->rowoffset = (banshee->vidDesktopOverlayStride & 0x3fff) >> 3;
+ svga->ma_latch = banshee->vidDesktopStartAddr >> 2;
+ banshee->desktop_stride_tiled = (banshee->vidDesktopOverlayStride & 0x3fff) * 128 * 32;
+// pclog("Extended shift out %i rowoffset=%i %02x\n", VIDPROCCFG_DESKTOP_PIX_FORMAT, svga->rowoffset, svga->crtc[1]);
+
+ svga->char_width = 8;
+ svga->split = 99999;
+
+ if (banshee->vidProcCfg & VIDPROCCFG_2X_MODE)
+ {
+ svga->hdisp *= 2;
+ svga->htotal *= 2;
+ }
+
+ svga->overlay.ena = banshee->vidProcCfg & VIDPROCCFG_OVERLAY_ENABLE;
+
+ svga->overlay.x = voodoo->overlay.start_x;
+ svga->overlay.y = voodoo->overlay.start_y;
+ svga->overlay.xsize = voodoo->overlay.size_x;
+ svga->overlay.ysize = voodoo->overlay.size_y;
+ svga->overlay.pitch = (banshee->vidDesktopOverlayStride & VID_STRIDE_OVERLAY_MASK) >> VID_STRIDE_OVERLAY_SHIFT;
+ if (banshee->vidProcCfg & VIDPROCCFG_OVERLAY_TILE)
+ svga->overlay.pitch *= 128*32;
+ if (svga->overlay.xsize <= 0 || svga->overlay.ysize <= 0)
+ svga->overlay.ena = 0;
+ if (svga->overlay.ena)
+ {
+/* pclog("Overlay enabled : start=%i,%i end=%i,%i size=%i,%i pitch=%x\n",
+ voodoo->overlay.start_x, voodoo->overlay.start_y,
+ voodoo->overlay.end_x, voodoo->overlay.end_y,
+ voodoo->overlay.size_x, voodoo->overlay.size_y,
+ svga->overlay.pitch);*/
+ if (!voodoo->overlay.start_x && !voodoo->overlay.start_y &&
+ svga->hdisp == voodoo->overlay.size_x && svga->dispend == voodoo->overlay.size_y)
+ {
+ /*Overlay is full screen, so don't bother rendering the desktop
+ behind it*/
+ svga->render = svga_render_null;
+ svga->bpp = 0;
+ }
+ }
+
+ svga->video_res_override = 1;
+ svga->video_res_x = svga->hdisp;
+ svga->video_res_y = svga->dispend;
+ svga->video_bpp = svga->bpp;
+ }
+ else
+ {
+// pclog("Normal shift out\n");
+ svga->bpp = 8;
+ svga->video_res_override = 0;
+ }
+
+ svga->fb_only = (banshee->vidProcCfg & VIDPROCCFG_VIDPROC_ENABLE);
+
+ if (((svga->miscout >> 2) & 3) == 3)
+ {
+ int k = banshee->pllCtrl0 & 3;
+ int m = (banshee->pllCtrl0 >> 2) & 0x3f;
+ int n = (banshee->pllCtrl0 >> 8) & 0xff;
+ double freq = (((double)n + 2) / (((double)m + 2) * (double)(1 << k))) * 14318184.0;
+
+ svga->clock = (cpuclock * (float)(1ull << 32)) / freq;
+// svga->clock = cpuclock / freq;
+
+// pclog("svga->clock = %g %g m=%i k=%i n=%i\n", freq, freq / 1000000.0, m, k, n);
+ }
+}
+
+static void banshee_ext_out(uint16_t addr, uint8_t val, void *p)
+{
+// banshee_t *banshee = (banshee_t *)p;
+// svga_t *svga = &banshee->svga;
+
+// pclog("banshee_ext_out: addr=%04x val=%02x\n", addr, val);
+
+ switch (addr & 0xff)
+ {
+ 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:
+ banshee_out((addr & 0xff)+0x300, val, p);
+ break;
+
+ default:
+ pclog("bad banshee_ext_out: addr=%04x val=%02x\n", addr, val);
+ }
+}
+static void banshee_ext_outl(uint16_t addr, uint32_t val, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ voodoo_t *voodoo = banshee->voodoo;
+ svga_t *svga = &banshee->svga;
+
+// pclog("banshee_ext_outl: addr=%04x val=%08x %04x(%08x):%08x\n", addr, val, CS,cs,cpu_state.pc);
+
+ switch (addr & 0xff)
+ {
+ case Init_pciInit0:
+ banshee->pciInit0 = val;
+ voodoo->read_time = pci_nonburst_time + pci_burst_time * ((val & 0x100) ? 2 : 1);
+ voodoo->burst_time = pci_burst_time * ((val & 0x200) ? 1 : 0);
+ voodoo->write_time = pci_nonburst_time + voodoo->burst_time;
+ break;
+
+ case Init_lfbMemoryConfig:
+ banshee->lfbMemoryConfig = val;
+// pclog("lfbMemoryConfig=%08x\n", val);
+ voodoo->tile_base = (val & 0x1fff) << 12;
+ voodoo->tile_stride = 1024 << ((val >> 13) & 7);
+ voodoo->tile_stride_shift = 10 + ((val >> 13) & 7);
+ voodoo->tile_x = ((val >> 16) & 0x7f) * 128;
+ voodoo->tile_x_real = ((val >> 16) & 0x7f) * 128*32;
+ break;
+
+ case Init_miscInit0:
+ banshee->miscInit0 = val;
+ voodoo->y_origin_swap = (val & MISCINIT0_Y_ORIGIN_SWAP_MASK) >> MISCINIT0_Y_ORIGIN_SWAP_SHIFT;
+ break;
+ case Init_miscInit1:
+ banshee->miscInit1 = val;
+ break;
+ case Init_dramInit0:
+ banshee->dramInit0 = val;
+ break;
+ case Init_dramInit1:
+ banshee->dramInit1 = val;
+ break;
+ case Init_agpInit0:
+ banshee->agpInit0 = val;
+ break;
+
+ case Init_2dCommand:
+ banshee->command_2d = val;
+ break;
+ case Init_2dSrcBaseAddr:
+ banshee->srcBaseAddr_2d = val;
+ break;
+ case Init_vgaInit0:
+ banshee->vgaInit0 = val;
+ break;
+ case Init_vgaInit1:
+ banshee->vgaInit1 = val;
+ svga->write_bank = (val & 0x3ff) << 15;
+ svga->read_bank = ((val >> 10) & 0x3ff) << 15;
+ break;
+
+ case PLL_pllCtrl0:
+ banshee->pllCtrl0 = val;
+ break;
+ case PLL_pllCtrl1:
+ banshee->pllCtrl1 = val;
+ break;
+ case PLL_pllCtrl2:
+ banshee->pllCtrl2 = val;
+ break;
+
+ case DAC_dacMode:
+ banshee->dacMode = val;
+ break;
+ case DAC_dacAddr:
+ banshee->dacAddr = val & 0x1ff;
+ break;
+ case DAC_dacData:
+ svga->pallook[banshee->dacAddr] = val & 0xffffff;
+ svga->fullchange = changeframecount;
+ break;
+
+ case Video_vidProcCfg:
+ banshee->vidProcCfg = val;
+// pclog("vidProcCfg=%08x\n", val);
+ banshee->overlay_pix_fmt = (val & VIDPROCCFG_OVERLAY_PIX_FORMAT_MASK) >> VIDPROCCFG_OVERLAY_PIX_FORMAT_SHIFT;
+ svga->hwcursor.ena = val & VIDPROCCFG_HWCURSOR_ENA;
+ svga->fullchange = changeframecount;
+ svga_recalctimings(svga);
+ break;
+
+ case Video_maxRgbDelta:
+ banshee->voodoo->scrfilterThreshold = val;
+ if (val > 0x00)
+ banshee->voodoo->scrfilterEnabled = 1;
+ else
+ banshee->voodoo->scrfilterEnabled = 0;
+ voodoo_threshold_check(banshee->voodoo);
+ pclog("Banshee Filter: %06x\n", val);
+
+ break;
+
+ case Video_hwCurPatAddr:
+ banshee->hwCurPatAddr = val;
+ svga->hwcursor.addr = (val & 0xfffff0) + (svga->hwcursor.yoff * 16);
+ break;
+ case Video_hwCurLoc:
+ banshee->hwCurLoc = val;
+ svga->hwcursor.x = (val & 0x7ff) - 32;
+ svga->hwcursor.y = ((val >> 16) & 0x7ff) - 64;
+ if (svga->hwcursor.y < 0)
+ {
+ svga->hwcursor.yoff = -svga->hwcursor.y;
+ svga->hwcursor.y = 0;
+ }
+ else
+ svga->hwcursor.yoff = 0;
+ svga->hwcursor.addr = (banshee->hwCurPatAddr & 0xfffff0) + (svga->hwcursor.yoff * 16);
+ svga->hwcursor.xsize = 64;
+ svga->hwcursor.ysize = 64;
+// pclog("hwCurLoc %08x %i\n", val, svga->hwcursor.y);
+ break;
+ case Video_hwCurC0:
+ banshee->hwCurC0 = val;
+ break;
+ case Video_hwCurC1:
+ banshee->hwCurC1 = val;
+ break;
+
+ case Video_vidSerialParallelPort:
+ banshee->vidSerialParallelPort = val;
+// pclog("vidSerialParallelPort: write %08x %08x %04x(%08x):%08x\n", val, val & (VIDSERIAL_DDC_DCK_W | VIDSERIAL_DDC_DDA_W), CS,cs,cpu_state.pc);
+ ddc_i2c_change((val & VIDSERIAL_DDC_DCK_W) ? 1 : 0, (val & VIDSERIAL_DDC_DDA_W) ? 1 : 0);
+ break;
+
+ case Video_vidScreenSize:
+ banshee->vidScreenSize = val;
+ voodoo->h_disp = (val & 0xfff) + 1;
+ voodoo->v_disp = (val >> 12) & 0xfff;
+ break;
+ case Video_vidOverlayStartCoords:
+ voodoo->overlay.vidOverlayStartCoords = val;
+ voodoo->overlay.start_x = val & OVERLAY_START_X_MASK;
+ voodoo->overlay.start_y = (val & OVERLAY_START_Y_MASK) >> OVERLAY_START_Y_SHIFT;
+ voodoo->overlay.size_x = voodoo->overlay.end_x - voodoo->overlay.start_x;
+ voodoo->overlay.size_y = voodoo->overlay.end_y - voodoo->overlay.start_y;
+ svga_recalctimings(svga);
+ break;
+ case Video_vidOverlayEndScreenCoords:
+ voodoo->overlay.vidOverlayEndScreenCoords = val;
+ voodoo->overlay.end_x = val & OVERLAY_END_X_MASK;
+ voodoo->overlay.end_y = (val & OVERLAY_END_Y_MASK) >> OVERLAY_END_Y_SHIFT;
+ voodoo->overlay.size_x = (voodoo->overlay.end_x - voodoo->overlay.start_x) + 1;
+ voodoo->overlay.size_y = (voodoo->overlay.end_y - voodoo->overlay.start_y) + 1;
+ svga_recalctimings(svga);
+ break;
+ case Video_vidOverlayDudx:
+ voodoo->overlay.vidOverlayDudx = val & VID_DUDX_MASK;
+// pclog("vidOverlayDudx=%08x\n", val);
+ break;
+ case Video_vidOverlayDudxOffsetSrcWidth:
+ voodoo->overlay.vidOverlayDudxOffsetSrcWidth = val;
+ voodoo->overlay.overlay_bytes = (val & OVERLAY_SRC_WIDTH_MASK) >> OVERLAY_SRC_WIDTH_SHIFT;
+// pclog("vidOverlayDudxOffsetSrcWidth=%08x\n", val);
+ break;
+ case Video_vidOverlayDvdy:
+ voodoo->overlay.vidOverlayDvdy = val & VID_DVDY_MASK;
+// pclog("vidOverlayDvdy=%08x\n", val);
+ break;
+ case Video_vidOverlayDvdyOffset:
+ voodoo->overlay.vidOverlayDvdyOffset = val;
+ break;
+
+
+ case Video_vidDesktopStartAddr:
+ banshee->vidDesktopStartAddr = val & 0xffffff;
+// pclog("vidDesktopStartAddr=%08x\n", val);
+ svga->fullchange = changeframecount;
+ svga_recalctimings(svga);
+ break;
+ case Video_vidDesktopOverlayStride:
+ banshee->vidDesktopOverlayStride = val;
+// pclog("vidDesktopOverlayStride=%08x\n", val);
+ svga->fullchange = changeframecount;
+ svga_recalctimings(svga);
+ break;
+// default:
+// fatal("bad banshee_ext_outl: addr=%04x val=%08x\n", addr, val);
+ }
+}
+
+static uint8_t banshee_ext_in(uint16_t addr, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+// svga_t *svga = &banshee->svga;
+ uint8_t ret = 0xff;
+
+ switch (addr & 0xff)
+ {
+ case Init_status: case Init_status+1: case Init_status+2: case Init_status+3:
+ ret = (banshee_status(banshee) >> ((addr & 3) * 8)) & 0xff;
+// pclog("Read status reg! %04x(%08x):%08x\n", CS, cs, cpu_state.pc);
+ break;
+
+ 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:
+ ret = banshee_in((addr & 0xff)+0x300, p);
+ break;
+
+ default:
+ pclog("bad banshee_ext_in: addr=%04x\n", addr);
+ break;
+ }
+
+// pclog("banshee_ext_in: addr=%04x val=%02x\n", addr, ret);
+
+ return ret;
+}
+
+static uint32_t banshee_status(banshee_t *banshee)
+{
+ voodoo_t *voodoo = banshee->voodoo;
+ svga_t *svga = &banshee->svga;
+ int fifo_entries = FIFO_ENTRIES;
+ int fifo_size = 0xffff - fifo_entries;
+ int swap_count = voodoo->swap_count;
+ int written = voodoo->cmd_written + voodoo->cmd_written_fifo;
+ int busy = (written - voodoo->cmd_read) || (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) ||
+ voodoo->render_voodoo_busy[0] || voodoo->render_voodoo_busy[1] ||
+ voodoo->render_voodoo_busy[2] || voodoo->render_voodoo_busy[3] ||
+ voodoo->voodoo_busy;
+ uint32_t ret;
+
+ ret = 0;
+ if (fifo_size < 0x20)
+ ret |= fifo_size;
+ else
+ ret |= 0x1f;
+ if (fifo_size)
+ ret |= 0x20;
+ if (swap_count < 7)
+ ret |= (swap_count << 28);
+ else
+ ret |= (7 << 28);
+ if (!(svga->cgastat & 8))
+ ret |= 0x40;
+
+ if (busy)
+ ret |= 0x780; /*Busy*/
+
+ if (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr)
+ ret |= (1 << 11);
+
+ if (!voodoo->voodoo_busy)
+ voodoo_wake_fifo_thread(voodoo);
+
+// pclog("banshee_status: busy %i %i (%i %i) %i %i %i %04x(%08x):%08x %08x\n", busy, written, voodoo->cmd_written, voodoo->cmd_written_fifo, voodoo->cmd_read, voodoo->cmdfifo_depth_rd, voodoo->cmdfifo_depth_wr, CS,cs,cpu_state.pc, ret);
+
+ return ret;
+}
+
+static uint32_t banshee_ext_inl(uint16_t addr, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ voodoo_t *voodoo = banshee->voodoo;
+ svga_t *svga = &banshee->svga;
+ uint32_t ret = 0xffffffff;
+
+ cycles -= voodoo->read_time;
+
+ switch (addr & 0xff)
+ {
+ case Init_status:
+ ret = banshee_status(banshee);
+// pclog("Read status reg! %04x(%08x):%08x\n", CS, cs, cpu_state.pc);
+ break;
+ case Init_pciInit0:
+ ret = banshee->pciInit0;
+ break;
+ case Init_lfbMemoryConfig:
+ ret = banshee->lfbMemoryConfig;
+ break;
+
+ case Init_miscInit0:
+ ret = banshee->miscInit0;
+ break;
+ case Init_miscInit1:
+ ret = banshee->miscInit1;
+ break;
+ case Init_dramInit0:
+ ret = banshee->dramInit0;
+ break;
+ case Init_dramInit1:
+ ret = banshee->dramInit1;
+ break;
+ case Init_agpInit0:
+ ret = banshee->agpInit0;
+ break;
+
+ case Init_vgaInit0:
+ ret = banshee->vgaInit0;
+ break;
+ case Init_vgaInit1:
+ ret = banshee->vgaInit1;
+ break;
+
+ case Init_2dCommand:
+ ret = banshee->command_2d;
+ break;
+ case Init_2dSrcBaseAddr:
+ ret = banshee->srcBaseAddr_2d;
+ break;
+ case Init_strapInfo:
+ ret = 0x00000040; /*8 MB SGRAM, PCI, IRQ enabled, 32kB BIOS*/
+ break;
+
+ case PLL_pllCtrl0:
+ ret = banshee->pllCtrl0;
+ break;
+ case PLL_pllCtrl1:
+ ret = banshee->pllCtrl1;
+ break;
+ case PLL_pllCtrl2:
+ ret = banshee->pllCtrl2;
+ break;
+
+ case DAC_dacMode:
+ ret = banshee->dacMode;
+ break;
+ case DAC_dacAddr:
+ ret = banshee->dacAddr;
+ break;
+ case DAC_dacData:
+ ret = svga->pallook[banshee->dacAddr];
+ break;
+
+ case Video_vidProcCfg:
+ ret = banshee->vidProcCfg;
+ break;
+
+ case Video_hwCurPatAddr:
+ ret = banshee->hwCurPatAddr;
+ break;
+ case Video_hwCurLoc:
+ ret = banshee->hwCurLoc;
+ break;
+ case Video_hwCurC0:
+ ret = banshee->hwCurC0;
+ break;
+ case Video_hwCurC1:
+ ret = banshee->hwCurC1;
+ break;
+
+ case Video_vidSerialParallelPort:
+ ret = banshee->vidSerialParallelPort & ~(VIDSERIAL_DDC_DCK_R | VIDSERIAL_DDC_DDA_R);
+ if ((banshee->vidSerialParallelPort & VIDSERIAL_DDC_DCK_W) && ddc_read_clock())
+ ret |= VIDSERIAL_DDC_DCK_R;
+ if ((banshee->vidSerialParallelPort & VIDSERIAL_DDC_DDA_W) && ddc_read_data())
+ ret |= VIDSERIAL_DDC_DDA_R;
+ ret = ret & ~(VIDSERIAL_I2C_SCK_R | VIDSERIAL_I2C_SDA_R);
+ if (banshee->vidSerialParallelPort & VIDSERIAL_I2C_SCK_W)
+ ret |= VIDSERIAL_I2C_SCK_R;
+ if (banshee->vidSerialParallelPort & VIDSERIAL_I2C_SDA_W)
+ ret |= VIDSERIAL_I2C_SDA_R;
+// pclog("vidSerialParallelPort: read %08x %08x %04x(%08x):%08x\n", ret, ret & (VIDSERIAL_DDC_DCK_R | VIDSERIAL_DDC_DDA_R), CS,cs,cpu_state.pc);
+ break;
+
+ case Video_vidScreenSize:
+ ret = banshee->vidScreenSize;
+ break;
+ case Video_vidOverlayStartCoords:
+ ret = voodoo->overlay.vidOverlayStartCoords;
+ break;
+ case Video_vidOverlayEndScreenCoords:
+ ret = voodoo->overlay.vidOverlayEndScreenCoords;
+ break;
+ case Video_vidOverlayDudx:
+ ret = voodoo->overlay.vidOverlayDudx;
+ break;
+ case Video_vidOverlayDudxOffsetSrcWidth:
+ ret = voodoo->overlay.vidOverlayDudxOffsetSrcWidth;
+ break;
+ case Video_vidOverlayDvdy:
+ ret = voodoo->overlay.vidOverlayDvdy;
+ break;
+ case Video_vidOverlayDvdyOffset:
+ ret = voodoo->overlay.vidOverlayDvdyOffset;
+ break;
+
+ case Video_vidDesktopStartAddr:
+ ret = banshee->vidDesktopStartAddr;
+ break;
+ case Video_vidDesktopOverlayStride:
+ ret = banshee->vidDesktopOverlayStride;
+ break;
+
+ default:
+// fatal("bad banshee_ext_inl: addr=%04x\n", addr);
+ break;
+ }
+
+// /*if (addr) */pclog("banshee_ext_inl: addr=%04x val=%08x\n", addr, ret);
+
+ return ret;
+}
+
+
+static uint32_t banshee_reg_readl(uint32_t addr, void *p);
+
+static uint8_t banshee_reg_read(uint32_t addr, void *p)
+{
+// pclog("banshee_reg_read: addr=%08x\n", addr);
+ return banshee_reg_readl(addr & ~3, p) >> (8*(addr & 3));
+}
+
+static uint16_t banshee_reg_readw(uint32_t addr, void *p)
+{
+// pclog("banshee_reg_readw: addr=%08x\n", addr);
+ return banshee_reg_readl(addr & ~3, p) >> (8*(addr & 2));
+}
+
+static uint32_t banshee_cmd_read(banshee_t *banshee, uint32_t addr)
+{
+ voodoo_t *voodoo = banshee->voodoo;
+ uint32_t ret = 0xffffffff;
+
+ switch (addr & 0x1fc)
+ {
+ case cmdBaseAddr0:
+ ret = voodoo->cmdfifo_base >> 12;
+// pclog("Read cmdfifo_base %08x\n", ret);
+ break;
+
+ case cmdRdPtrL0:
+ ret = voodoo->cmdfifo_rp;
+// pclog("Read cmdfifo_rp %08x\n", ret);
+ break;
+
+ case cmdFifoDepth0:
+ ret = voodoo->cmdfifo_depth_wr - voodoo->cmdfifo_depth_rd;
+// pclog("Read cmdfifo_depth %08x\n", ret);
+ break;
+
+ case 0x108:
+ break;
+
+#ifndef RELEASE_BUILD
+ default:
+ fatal("Unknown banshee_cmd_read %08x\n", addr);
+#endif
+ }
+
+ return ret;
+}
+
+static uint32_t banshee_reg_readl(uint32_t addr, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ voodoo_t *voodoo = banshee->voodoo;
+ uint32_t ret = 0xffffffff;
+
+ cycles -= voodoo->read_time;
+
+ switch (addr & 0x1f00000)
+ {
+ case 0x0000000: /*IO remap*/
+ if (!(addr & 0x80000))
+ ret = banshee_ext_inl(addr & 0xff, banshee);
+ else
+ ret = banshee_cmd_read(banshee, addr);
+ break;
+
+ case 0x0100000: /*2D registers*/
+ voodoo_flush(voodoo);
+ switch (addr & 0x1fc)
+ {
+ case 0x08:
+ ret = voodoo->banshee_blt.clip0Min;
+ break;
+ case 0x0c:
+ ret = voodoo->banshee_blt.clip0Max;
+ break;
+ case 0x10:
+ ret = voodoo->banshee_blt.dstBaseAddr;
+ break;
+ case 0x14:
+ ret = voodoo->banshee_blt.dstFormat;
+ break;
+ case 0x34:
+ ret = voodoo->banshee_blt.srcBaseAddr;
+ break;
+ case 0x38:
+ ret = voodoo->banshee_blt.commandExtra;
+ break;
+ case 0x5c:
+ ret = voodoo->banshee_blt.srcXY;
+ break;
+ case 0x60:
+ ret = voodoo->banshee_blt.colorBack;
+ break;
+ case 0x64:
+ ret = voodoo->banshee_blt.colorFore;
+ break;
+ case 0x68:
+ ret = voodoo->banshee_blt.dstSize;
+ break;
+ case 0x6c:
+ ret = voodoo->banshee_blt.dstXY;
+ break;
+ case 0x70:
+ ret = voodoo->banshee_blt.command;
+ break;
+ default:
+ pclog("banshee_reg_readl: addr=%08x\n", addr);
+ }
+ break;
+
+ case 0x0200000: case 0x0300000: case 0x0400000: case 0x0500000: /*3D registers*/
+ switch (addr & 0x3fc)
+ {
+ case SST_status:
+ ret = banshee_status(banshee);
+ break;
+
+ case SST_intrCtrl:
+ ret = banshee->intrCtrl & 0x0030003f;
+ break;
+
+ case SST_fbzColorPath:
+ voodoo_flush(voodoo);
+ ret = voodoo->params.fbzColorPath;
+ break;
+ case SST_fogMode:
+ voodoo_flush(voodoo);
+ ret = voodoo->params.fogMode;
+ break;
+ case SST_alphaMode:
+ voodoo_flush(voodoo);
+ ret = voodoo->params.alphaMode;
+ break;
+ case SST_fbzMode:
+ voodoo_flush(voodoo);
+ ret = voodoo->params.fbzMode;
+ break;
+ case SST_lfbMode:
+ voodoo_flush(voodoo);
+ ret = voodoo->lfbMode;
+ break;
+ case SST_clipLeftRight:
+ ret = voodoo->params.clipRight | (voodoo->params.clipLeft << 16);
+ break;
+ case SST_clipLowYHighY:
+ ret = voodoo->params.clipHighY | (voodoo->params.clipLowY << 16);
+ break;
+
+ case SST_clipLeftRight1:
+ ret = voodoo->params.clipRight1 | (voodoo->params.clipLeft1 << 16);
+ break;
+ case SST_clipTopBottom1:
+ ret = voodoo->params.clipHighY1 | (voodoo->params.clipLowY1 << 16);
+ break;
+
+ case SST_stipple:
+ voodoo_flush(voodoo);
+ ret = voodoo->params.stipple;
+ break;
+ case SST_color0:
+ voodoo_flush(voodoo);
+ ret = voodoo->params.color0;
+ break;
+ case SST_color1:
+ voodoo_flush(voodoo);
+ ret = voodoo->params.color1;
+ break;
+
+ case SST_fbiPixelsIn:
+ ret = voodoo->fbiPixelsIn & 0xffffff;
+ break;
+ case SST_fbiChromaFail:
+ ret = voodoo->fbiChromaFail & 0xffffff;
+ break;
+ case SST_fbiZFuncFail:
+ ret = voodoo->fbiZFuncFail & 0xffffff;
+ break;
+ case SST_fbiAFuncFail:
+ ret = voodoo->fbiAFuncFail & 0xffffff;
+ break;
+ case SST_fbiPixelsOut:
+ ret = voodoo->fbiPixelsOut & 0xffffff;
+ break;
+
+ default:
+ pclog("banshee_reg_readl: 3D addr=%08x\n", addr);
+ break;
+ }
+ break;
+ }
+
+// /*if (addr != 0xe0000000) */pclog("banshee_reg_readl: addr=%08x ret=%08x %04x(%08x):%08x\n", addr, ret, CS,cs,cpu_state.pc);
+// if (cpu_state.pc == 0x1000e437)
+// output = 3;
+ return ret;
+}
+
+static void banshee_reg_write(uint32_t addr, uint8_t val, void *p)
+{
+// pclog("banshee_reg_writeb: addr=%08x val=%02x\n", addr, val);
+}
+
+static void banshee_reg_writew(uint32_t addr, uint16_t val, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ voodoo_t *voodoo = banshee->voodoo;
+
+ cycles -= voodoo->write_time;
+
+// pclog("banshee_reg_writew: addr=%08x val=%04x\n", addr, val);
+ switch (addr & 0x1f00000)
+ {
+ case 0x1000000: case 0x1100000: case 0x1200000: case 0x1300000: /*3D LFB*/
+ case 0x1400000: case 0x1500000: case 0x1600000: case 0x1700000:
+ case 0x1800000: case 0x1900000: case 0x1a00000: case 0x1b00000:
+ case 0x1c00000: case 0x1d00000: case 0x1e00000: case 0x1f00000:
+ voodoo_queue_command(voodoo, (addr & 0xffffff) | FIFO_WRITEW_FB, val);
+ break;
+ }
+}
+
+static void banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val)
+{
+ voodoo_t *voodoo = banshee->voodoo;
+// pclog("banshee_cmd_write: addr=%03x val=%08x\n", addr & 0x1fc, val);
+ switch (addr & 0x1fc)
+ {
+ case cmdBaseAddr0:
+ voodoo->cmdfifo_base = (val & 0xfff) << 12;
+ voodoo->cmdfifo_end = voodoo->cmdfifo_base + (((voodoo->cmdfifo_size & 0xff) + 1) << 12);
+// pclog("cmdfifo_base=%08x cmdfifo_end=%08x %08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end, val);
+ break;
+
+ case cmdBaseSize0:
+ voodoo->cmdfifo_size = val;
+ voodoo->cmdfifo_end = voodoo->cmdfifo_base + (((voodoo->cmdfifo_size & 0xff) + 1) << 12);
+ voodoo->cmdfifo_enabled = val & 0x100;
+ if (!voodoo->cmdfifo_enabled)
+ voodoo->cmdfifo_in_sub = 0; /*Not sure exactly when this should be reset*/
+// pclog("cmdfifo_base=%08x cmdfifo_end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end);
+ break;
+
+// voodoo->cmdfifo_end = ((val >> 16) & 0x3ff) << 12;
+// pclog("CMDFIFO base=%08x end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end);
+// break;
+
+ case cmdRdPtrL0:
+ voodoo->cmdfifo_rp = val;
+ break;
+ case cmdAMin0:
+ voodoo->cmdfifo_amin = val;
+ break;
+ case cmdAMax0:
+ voodoo->cmdfifo_amax = val;
+ break;
+ case cmdFifoDepth0:
+ voodoo->cmdfifo_depth_rd = 0;
+ voodoo->cmdfifo_depth_wr = val & 0xffff;
+ break;
+
+ default:
+ pclog("Unknown banshee_cmd_write: addr=%08x val=%08x\n", addr, val);
+ break;
+ }
+
+/* cmdBaseSize0 = 0x24,
+ cmdBump0 = 0x28,
+ cmdRdPtrL0 = 0x2c,
+ cmdRdPtrH0 = 0x30,
+ cmdAMin0 = 0x34,
+ cmdAMax0 = 0x3c,
+ cmdFifoDepth0 = 0x44,
+ cmdHoleCnt0 = 0x48
+ }*/
+}
+
+static void banshee_reg_writel(uint32_t addr, uint32_t val, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ voodoo_t *voodoo = banshee->voodoo;
+
+ if (addr == voodoo->last_write_addr+4)
+ cycles -= voodoo->burst_time;
+ else
+ cycles -= voodoo->write_time;
+ voodoo->last_write_addr = addr;
+
+// pclog("banshee_reg_writel: addr=%08x val=%08x\n", addr, val);
+
+ switch (addr & 0x1f00000)
+ {
+ case 0x0000000: /*IO remap*/
+ if (!(addr & 0x80000))
+ banshee_ext_outl(addr & 0xff, val, banshee);
+ else
+ banshee_cmd_write(banshee, addr, val);
+// pclog("CMD!!! write %08x %08x\n", addr, val);
+ break;
+
+ case 0x0100000: /*2D registers*/
+ voodoo_queue_command(voodoo, (addr & 0x1fc) | FIFO_WRITEL_2DREG, val);
+ break;
+
+ case 0x0200000: case 0x0300000: case 0x0400000: case 0x0500000: /*3D registers*/
+ switch (addr & 0x3fc)
+ {
+ case SST_intrCtrl:
+ banshee->intrCtrl = val & 0x0030003f;
+// pclog("intrCtrl=%08x\n", val);
+ break;
+
+ case SST_userIntrCMD:
+#ifndef RELEASE_BUILD
+ fatal("userIntrCMD write %08x\n", val);
+#endif
+ break;
+
+ case SST_swapbufferCMD:
+ voodoo->cmd_written++;
+ voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val);
+ if (!voodoo->voodoo_busy)
+ voodoo_wake_fifo_threads(voodoo->set, voodoo);
+// pclog("SST_swapbufferCMD write: %i %i\n", voodoo->cmd_written, voodoo->cmd_written_fifo);
+ break;
+ case SST_triangleCMD:
+ voodoo->cmd_written++;
+ voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val);
+ if (!voodoo->voodoo_busy)
+ voodoo_wake_fifo_threads(voodoo->set, voodoo);
+ break;
+ case SST_ftriangleCMD:
+ voodoo->cmd_written++;
+ voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val);
+ if (!voodoo->voodoo_busy)
+ voodoo_wake_fifo_threads(voodoo->set, voodoo);
+ break;
+ case SST_fastfillCMD:
+ voodoo->cmd_written++;
+ voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val);
+ if (!voodoo->voodoo_busy)
+ voodoo_wake_fifo_threads(voodoo->set, voodoo);
+ break;
+ case SST_nopCMD:
+ voodoo->cmd_written++;
+ voodoo_queue_command(voodoo, (addr & 0x3fc) | FIFO_WRITEL_REG, val);
+ if (!voodoo->voodoo_busy)
+ voodoo_wake_fifo_threads(voodoo->set, voodoo);
+ break;
+
+ case SST_swapPending:
+ thread_lock_mutex(voodoo->swap_mutex);
+ voodoo->swap_count++;
+ thread_unlock_mutex(voodoo->swap_mutex);
+// voodoo->cmd_written++;
+ break;
+
+ default:
+ voodoo_queue_command(voodoo, (addr & 0x3ffffc) | FIFO_WRITEL_REG, val);
+ break;
+ }
+ break;
+
+ case 0x0600000: case 0x0700000: /*Texture download*/
+ voodoo->tex_count++;
+ voodoo_queue_command(voodoo, (addr & 0x1ffffc) | FIFO_WRITEL_TEX, val);
+ break;
+
+ case 0x1000000: case 0x1100000: case 0x1200000: case 0x1300000: /*3D LFB*/
+ case 0x1400000: case 0x1500000: case 0x1600000: case 0x1700000:
+ case 0x1800000: case 0x1900000: case 0x1a00000: case 0x1b00000:
+ case 0x1c00000: case 0x1d00000: case 0x1e00000: case 0x1f00000:
+ voodoo_queue_command(voodoo, (addr & 0xfffffc) | FIFO_WRITEL_FB, val);
+ break;
+ }
+}
+
+static uint8_t banshee_read_linear(uint32_t addr, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ voodoo_t *voodoo = banshee->voodoo;
+ svga_t *svga = &banshee->svga;
+
+ cycles -= voodoo->read_time;
+ cycles_lost += voodoo->read_time;
+
+ addr &= svga->decode_mask;
+ if (addr >= voodoo->tile_base)
+ {
+ int x, y;
+
+ addr -= voodoo->tile_base;
+ x = addr & (voodoo->tile_stride-1);
+ y = addr >> voodoo->tile_stride_shift;
+
+ addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128*32) + ((y & 31) * 128) + (y >> 5)*voodoo->tile_x_real;
+// pclog(" Tile rb %08x->%08x %i %i\n", old_addr, addr, x, y);
+ }
+ if (addr >= svga->vram_max)
+ return 0xff;
+
+ egareads++;
+ cycles -= video_timing_read_b;
+ cycles_lost += video_timing_read_b;
+
+// pclog("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]);
+
+ return svga->vram[addr & svga->vram_mask];
+}
+
+static uint16_t banshee_read_linear_w(uint32_t addr, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ voodoo_t *voodoo = banshee->voodoo;
+ svga_t *svga = &banshee->svga;
+
+ if (addr & 1)
+ return banshee_read_linear(addr, p) | (banshee_read_linear(addr+1, p) << 8);
+
+ cycles -= voodoo->read_time;
+ cycles_lost += voodoo->read_time;
+
+ addr &= svga->decode_mask;
+ if (addr >= voodoo->tile_base)
+ {
+ int x, y;
+
+ addr -= voodoo->tile_base;
+ x = addr & (voodoo->tile_stride-1);
+ y = addr >> voodoo->tile_stride_shift;
+
+ addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128*32) + ((y & 31) * 128) + (y >> 5)*voodoo->tile_x_real;
+// pclog(" Tile rb %08x->%08x %i %i\n", old_addr, addr, x, y);
+ }
+ if (addr >= svga->vram_max)
+ return 0xff;
+
+ egareads++;
+ cycles -= video_timing_read_w;
+ cycles_lost += video_timing_read_w;
+
+// pclog("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]);
+
+ return *(uint16_t *)&svga->vram[addr & svga->vram_mask];
+}
+
+static uint32_t banshee_read_linear_l(uint32_t addr, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ voodoo_t *voodoo = banshee->voodoo;
+ svga_t *svga = &banshee->svga;
+
+ if (addr & 3)
+ return banshee_read_linear_w(addr, p) | (banshee_read_linear_w(addr+2, p) << 16);
+
+ cycles -= voodoo->read_time;
+ cycles_lost += voodoo->read_time;
+
+ addr &= svga->decode_mask;
+ if (addr >= voodoo->tile_base)
+ {
+ int x, y;
+
+ addr -= voodoo->tile_base;
+ x = addr & (voodoo->tile_stride-1);
+ y = addr >> voodoo->tile_stride_shift;
+
+ addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128*32) + ((y & 31) * 128) + (y >> 5)*voodoo->tile_x_real;
+// pclog(" Tile rb %08x->%08x %i %i\n", old_addr, addr, x, y);
+ }
+ if (addr >= svga->vram_max)
+ return 0xff;
+
+ egareads++;
+ cycles -= video_timing_read_l;
+ cycles_lost += video_timing_read_l;
+
+// pclog("read_linear: addr=%08x val=%02x\n", addr, svga->vram[addr & svga->vram_mask]);
+
+ return *(uint32_t *)&svga->vram[addr & svga->vram_mask];
+}
+
+static void banshee_write_linear(uint32_t addr, uint8_t val, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ voodoo_t *voodoo = banshee->voodoo;
+ svga_t *svga = &banshee->svga;
+
+ cycles -= voodoo->write_time;
+ cycles_lost += voodoo->write_time;
+
+// pclog("write_linear: addr=%08x val=%02x\n", addr, val);
+ addr &= svga->decode_mask;
+ if (addr >= voodoo->tile_base)
+ {
+ int x, y;
+
+ addr -= voodoo->tile_base;
+ x = addr & (voodoo->tile_stride-1);
+ y = addr >> voodoo->tile_stride_shift;
+
+ addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128*32) + ((y & 31) * 128) + (y >> 5)*voodoo->tile_x_real;
+// pclog(" Tile b %08x->%08x %i %i\n", old_addr, addr, x, y);
+ }
+ if (addr >= svga->vram_max)
+ return;
+
+ egawrites++;
+
+ cycles -= video_timing_write_b;
+ cycles_lost += video_timing_write_b;
+
+ svga->changedvram[addr >> 12] = changeframecount;
+ svga->vram[addr & svga->vram_mask] = val;
+}
+
+static void banshee_write_linear_w(uint32_t addr, uint16_t val, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ voodoo_t *voodoo = banshee->voodoo;
+ svga_t *svga = &banshee->svga;
+
+ if (addr & 1)
+ {
+ banshee_write_linear(addr, val, p);
+ banshee_write_linear(addr + 1, val >> 8, p);
+ return;
+ }
+
+ cycles -= voodoo->write_time;
+ cycles_lost += voodoo->write_time;
+
+// pclog("write_linear: addr=%08x val=%02x\n", addr, val);
+ addr &= svga->decode_mask;
+ if (addr >= voodoo->tile_base)
+ {
+ int x, y;
+
+ addr -= voodoo->tile_base;
+ x = addr & (voodoo->tile_stride-1);
+ y = addr >> voodoo->tile_stride_shift;
+
+ addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128*32) + ((y & 31) * 128) + (y >> 5)*voodoo->tile_x_real;
+// pclog(" Tile b %08x->%08x %i %i\n", old_addr, addr, x, y);
+ }
+ if (addr >= svga->vram_max)
+ return;
+
+ egawrites++;
+
+ cycles -= video_timing_write_w;
+ cycles_lost += video_timing_write_w;
+
+ svga->changedvram[addr >> 12] = changeframecount;
+ *(uint16_t *)&svga->vram[addr & svga->vram_mask] = val;
+}
+
+static void banshee_write_linear_l(uint32_t addr, uint32_t val, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ voodoo_t *voodoo = banshee->voodoo;
+ svga_t *svga = &banshee->svga;
+ int timing;
+
+ if (addr & 3)
+ {
+ banshee_write_linear_w(addr, val, p);
+ banshee_write_linear_w(addr + 2, val >> 16, p);
+ return;
+ }
+
+ if (addr == voodoo->last_write_addr+4)
+ timing = voodoo->burst_time;
+ else
+ timing = voodoo->write_time;
+ cycles -= timing;
+ cycles_lost += timing;
+ voodoo->last_write_addr = addr;
+
+// /*if (val) */pclog("write_linear_l: addr=%08x val=%08x %08x\n", addr, val, voodoo->tile_base);
+ addr &= svga->decode_mask;
+ if (addr >= voodoo->tile_base)
+ {
+ int x, y;
+
+ addr -= voodoo->tile_base;
+ x = addr & (voodoo->tile_stride-1);
+ y = addr >> voodoo->tile_stride_shift;
+
+ addr = voodoo->tile_base + (x & 127) + ((x >> 7) * 128*32) + ((y & 31) * 128) + (y >> 5)*voodoo->tile_x_real;
+// pclog(" Tile %08x->%08x->%08x->%08x %i %i tile_x=%i\n", old_addr, addr_off, addr2, addr, x, y, voodoo->tile_x_real);
+ }
+
+ if (addr >= svga->vram_max)
+ return;
+
+ egawrites += 4;
+
+ cycles -= video_timing_write_l;
+ cycles_lost += video_timing_write_l;
+
+ svga->changedvram[addr >> 12] = changeframecount;
+ *(uint32_t *)&svga->vram[addr & svga->vram_mask] = val;
+ if (voodoo->cmdfifo_enabled && addr >= voodoo->cmdfifo_base && addr < voodoo->cmdfifo_end)
+ {
+// pclog("CMDFIFO write %08x %08x old amin=%08x amax=%08x hlcnt=%i depth_wr=%i rp=%08x\n", addr, val, voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, voodoo->cmdfifo_holecount, voodoo->cmdfifo_depth_wr, voodoo->cmdfifo_rp);
+ if (addr == voodoo->cmdfifo_base && !voodoo->cmdfifo_holecount)
+ {
+// if (voodoo->cmdfifo_holecount)
+// fatal("CMDFIFO reset pointers while outstanding holes\n");
+ /*Reset pointers*/
+ voodoo->cmdfifo_amin = voodoo->cmdfifo_base;
+ voodoo->cmdfifo_amax = voodoo->cmdfifo_base;
+ voodoo->cmdfifo_depth_wr++;
+ voodoo_wake_fifo_thread(voodoo);
+ }
+ else if (voodoo->cmdfifo_holecount)
+ {
+// if ((addr <= voodoo->cmdfifo_amin && voodoo->cmdfifo_amin != -4) || addr >= voodoo->cmdfifo_amax)
+// fatal("CMDFIFO holecount write outside of amin/amax - amin=%08x amax=%08x holecount=%i\n", voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, voodoo->cmdfifo_holecount);
+// pclog("holecount %i\n", voodoo->cmdfifo_holecount);
+ voodoo->cmdfifo_holecount--;
+ if (!voodoo->cmdfifo_holecount)
+ {
+ /*Filled in holes, resume normal operation*/
+ voodoo->cmdfifo_depth_wr += ((voodoo->cmdfifo_amax - voodoo->cmdfifo_amin) >> 2);
+ voodoo->cmdfifo_amin = voodoo->cmdfifo_amax;
+ voodoo_wake_fifo_thread(voodoo);
+// pclog("hole filled! amin=%08x amax=%08x added %i words\n", voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, words_to_add);
+ }
+ }
+ else if (addr == voodoo->cmdfifo_amax+4)
+ {
+ /*In-order write*/
+ voodoo->cmdfifo_amin = addr;
+ voodoo->cmdfifo_amax = addr;
+ voodoo->cmdfifo_depth_wr++;
+ voodoo_wake_fifo_thread(voodoo);
+ }
+ else
+ {
+ /*Out-of-order write*/
+ if (addr < voodoo->cmdfifo_amin)
+ {
+ /*Reset back to start. Note that write is still out of order!*/
+ voodoo->cmdfifo_amin = voodoo->cmdfifo_base-4;
+
+ }
+// else if (addr < voodoo->cmdfifo_amax)
+// fatal("Out-of-order write really out of order\n");
+ voodoo->cmdfifo_amax = addr;
+ voodoo->cmdfifo_holecount = ((voodoo->cmdfifo_amax - voodoo->cmdfifo_amin) >> 2) - 1;
+// pclog("CMDFIFO out of order: amin=%08x amax=%08x holecount=%i\n", voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, voodoo->cmdfifo_holecount);
+ }
+ }
+}
+
+void banshee_hwcursor_draw(svga_t *svga, int displine)
+{
+ banshee_t *banshee = (banshee_t *)svga->p;
+ int x, c;
+ int x_off;
+ uint32_t col0 = banshee->hwCurC0;
+ uint32_t col1 = banshee->hwCurC1;
+ uint8_t plane0[8], plane1[8];
+
+ for (c = 0; c < 8; c++)
+ plane0[c] = svga->vram[svga->hwcursor_latch.addr + c];
+ for (c = 0; c < 8; c++)
+ plane1[c] = svga->vram[svga->hwcursor_latch.addr + c + 8];
+ svga->hwcursor_latch.addr += 16;
+
+ x_off = svga->hwcursor_latch.x;
+
+ if (banshee->vidProcCfg & VIDPROCCFG_CURSOR_MODE)
+ {
+ /*X11 mode*/
+ for (x = 0; x < 64; x += 8)
+ {
+ if (x_off > (32-8))
+ {
+ int xx;
+
+ for (xx = 0; xx < 8; xx++)
+ {
+ if (plane0[x >> 3] & (1 << 7))
+ ((uint32_t *)buffer32->line[displine])[x_off + xx] = (plane1[x >> 3] & (1 << 7)) ? col1 : col0;
+
+ plane0[x >> 3] <<= 1;
+ plane1[x >> 3] <<= 1;
+ }
+ }
+
+ x_off += 8;
+ }
+ }
+ else
+ {
+ /*Windows mode*/
+ for (x = 0; x < 64; x += 8)
+ {
+ if (x_off > (32-8))
+ {
+ int xx;
+
+ for (xx = 0; xx < 8; xx++)
+ {
+ if (!(plane0[x >> 3] & (1 << 7)))
+ ((uint32_t *)buffer32->line[displine])[x_off + xx] = (plane1[x >> 3] & (1 << 7)) ? col1 : col0;
+ else if (plane1[x >> 3] & (1 << 7))
+ ((uint32_t *)buffer32->line[displine])[x_off + xx] ^= 0xffffff;
+
+ plane0[x >> 3] <<= 1;
+ plane1[x >> 3] <<= 1;
+ }
+ }
+
+ x_off += 8;
+ }
+ }
+}
+
+#define CLAMP(x) do \
+ { \
+ if ((x) & ~0xff) \
+ x = ((x) < 0) ? 0 : 0xff; \
+ } \
+ while (0)
+
+#define DECODE_RGB565(buf) \
+ do \
+ { \
+ int c; \
+ int wp = 0; \
+ \
+ for (c = 0; c < voodoo->overlay.overlay_bytes; c += 2) \
+ { \
+ uint16_t data = *(uint16_t *)src; \
+ int r = data & 0x1f; \
+ int g = (data >> 5) & 0x3f; \
+ int b = data >> 11; \
+ \
+ if (banshee->vidProcCfg & VIDPROCCFG_OVERLAY_CLUT_BYPASS) \
+ buf[wp++] = (r << 3) | (g << 10) | (b << 19); \
+ else \
+ buf[wp++] = (clut[r << 3] & 0x0000ff) | \
+ (clut[g << 2] & 0x00ff00) | \
+ (clut[b << 3] & 0xff0000); \
+ src += 2; \
+ } \
+ } while (0)
+
+#define DECODE_RGB565_TILED(buf) \
+ do \
+ { \
+ int c; \
+ int wp = 0; \
+ uint32_t base_addr = (buf == banshee->overlay_buffer[1]) ? src_addr2 : src_addr; \
+ \
+ for (c = 0; c < voodoo->overlay.overlay_bytes; c += 2) \
+ { \
+ uint16_t data = *(uint16_t *)&svga->vram[(base_addr + (c & 127) + (c >> 7)*128*32) & svga->vram_mask]; \
+ int r = data & 0x1f; \
+ int g = (data >> 5) & 0x3f; \
+ int b = data >> 11; \
+ \
+ if (banshee->vidProcCfg & VIDPROCCFG_OVERLAY_CLUT_BYPASS) \
+ buf[wp++] = (r << 3) | (g << 10) | (b << 19); \
+ else \
+ buf[wp++] = (clut[r << 3] & 0x0000ff) | \
+ (clut[g << 2] & 0x00ff00) | \
+ (clut[b << 3] & 0xff0000); \
+ } \
+ } while (0)
+
+#define DECODE_YUYV422(buf) \
+ do \
+ { \
+ int c; \
+ int wp = 0; \
+ \
+ for (c = 0; c < voodoo->overlay.overlay_bytes; c += 4) \
+ { \
+ uint8_t y1, y2; \
+ int8_t Cr, Cb; \
+ int dR, dG, dB; \
+ int r, g, b; \
+ \
+ y1 = src[0]; \
+ Cr = src[1] - 0x80; \
+ y2 = src[2]; \
+ Cb = src[3] - 0x80; \
+ src += 4; \
+ \
+ dR = (359*Cr) >> 8; \
+ dG = (88*Cb + 183*Cr) >> 8; \
+ dB = (453*Cb) >> 8; \
+ \
+ r = y1 + dR; \
+ CLAMP(r); \
+ g = y1 - dG; \
+ CLAMP(g); \
+ b = y1 + dB; \
+ CLAMP(b); \
+ buf[wp++] = r | (g << 8) | (b << 16); \
+ \
+ r = y2 + dR; \
+ CLAMP(r); \
+ g = y2 - dG; \
+ CLAMP(g); \
+ b = y2 + dB; \
+ CLAMP(b); \
+ buf[wp++] = r | (g << 8) | (b << 16); \
+ } \
+ } while (0)
+
+#define DECODE_UYUV422(buf) \
+ do \
+ { \
+ int c; \
+ int wp = 0; \
+ \
+ for (c = 0; c < voodoo->overlay.overlay_bytes; c += 4) \
+ { \
+ uint8_t y1, y2; \
+ int8_t Cr, Cb; \
+ int dR, dG, dB; \
+ int r, g, b; \
+ \
+ Cr = src[0] - 0x80; \
+ y1 = src[1]; \
+ Cb = src[2] - 0x80; \
+ y2 = src[3]; \
+ src += 4; \
+ \
+ dR = (359*Cr) >> 8; \
+ dG = (88*Cb + 183*Cr) >> 8; \
+ dB = (453*Cb) >> 8; \
+ \
+ r = y1 + dR; \
+ CLAMP(r); \
+ g = y1 - dG; \
+ CLAMP(g); \
+ b = y1 + dB; \
+ CLAMP(b); \
+ buf[wp++] = r | (g << 8) | (b << 16); \
+ \
+ r = y2 + dR; \
+ CLAMP(r); \
+ g = y2 - dG; \
+ CLAMP(g); \
+ b = y2 + dB; \
+ CLAMP(b); \
+ buf[wp++] = r | (g << 8) | (b << 16); \
+ } \
+ } while (0)
+
+
+#define OVERLAY_SAMPLE(buf) \
+ do \
+ { \
+ switch (banshee->overlay_pix_fmt) \
+ { \
+ case 0: \
+ break; \
+ \
+ case OVERLAY_FMT_YUYV422: \
+ DECODE_YUYV422(buf); \
+ break; \
+ \
+ case OVERLAY_FMT_UYVY422: \
+ DECODE_UYUV422(buf); \
+ break; \
+ \
+ case OVERLAY_FMT_565: \
+ case OVERLAY_FMT_565_DITHER: \
+ if (banshee->vidProcCfg & VIDPROCCFG_OVERLAY_TILE) \
+ DECODE_RGB565_TILED(buf); \
+ else \
+ DECODE_RGB565(buf); \
+ break; \
+ } \
+ } while (0)
+
+/* generate both filters for the static table here */
+void voodoo_generate_vb_filters(voodoo_t *voodoo, int fcr, int fcg)
+{
+ int g, h;
+ float difference, diffg;
+ float thiscol, thiscolg;
+ float clr, clg = 0;
+ float hack = 1.0f;
+ // pre-clamping
+
+ fcr *= hack;
+ fcg *= hack;
+
+
+ /* box prefilter */
+ for (g=0;g<256;g++) // pixel 1 - our target pixel we want to bleed into
+ {
+ for (h=0;h<256;h++) // pixel 2 - our main pixel
+ {
+ float avg;
+ float avgdiff;
+
+ difference = (float)(g - h);
+ avg = g;
+ avgdiff = avg - h;
+
+ avgdiff = avgdiff * 0.75f;
+ if (avgdiff < 0) avgdiff *= -1;
+ if (difference < 0) difference *= -1;
+
+ thiscol = thiscolg = g;
+
+ if (h > g)
+ {
+ clr = clg = avgdiff;
+
+ if (clr>fcr) clr=fcr;
+ if (clg>fcg) clg=fcg;
+
+ thiscol = g;
+ thiscolg = g;
+
+ if (thiscol>g+fcr)
+ thiscol=g+fcr;
+ if (thiscolg>g+fcg)
+ thiscolg=g+fcg;
+
+ if (thiscol>g+difference)
+ thiscol=g+difference;
+ if (thiscolg>g+difference)
+ thiscolg=g+difference;
+
+ // hmm this might not be working out..
+ int ugh = g - h;
+ if (ugh < fcr)
+ thiscol = h;
+ if (ugh < fcg)
+ thiscolg = h;
+ }
+
+ if (difference > fcr)
+ thiscol = g;
+ if (difference > fcg)
+ thiscolg = g;
+
+ // clamp
+ if (thiscol < 0) thiscol = 0;
+ if (thiscolg < 0) thiscolg = 0;
+
+ if (thiscol > 255) thiscol = 255;
+ if (thiscolg > 255) thiscolg = 255;
+
+ vb_filter_bx_rb[g][h] = (thiscol);
+ vb_filter_bx_g [g][h] = (thiscolg);
+
+ }
+ float lined = g + 4;
+ if (lined > 255)
+ lined = 255;
+ voodoo->purpleline[g][0] = lined;
+ voodoo->purpleline[g][2] = lined;
+
+ lined = g + 0;
+ if (lined > 255)
+ lined = 255;
+ voodoo->purpleline[g][1] = lined;
+ }
+
+ /* 4x1 and 2x2 filter */
+ //fcr *= 5;
+ //fcg *= 6;
+
+ for (g=0;g<256;g++) // pixel 1
+ {
+ for (h=0;h<256;h++) // pixel 2
+ {
+ difference = (float)(h - g);
+ diffg = difference;
+
+ thiscol = thiscolg = g;
+
+ if (difference > fcr)
+ difference = fcr;
+ if (difference < -fcr)
+ difference = -fcr;
+
+ if (diffg > fcg)
+ diffg = fcg;
+ if (diffg < -fcg)
+ diffg = -fcg;
+
+ if ((difference < fcr) || (-difference > -fcr))
+ thiscol = g + (difference / 2);
+ if ((diffg < fcg) || (-diffg > -fcg))
+ thiscolg = g + (diffg / 2);
+
+ if (thiscol < 0)
+ thiscol = 0;
+ if (thiscol > 255)
+ thiscol = 255;
+
+ if (thiscolg < 0)
+ thiscolg = 0;
+ if (thiscolg > 255)
+ thiscolg = 255;
+
+ vb_filter_v1_rb[g][h] = thiscol;
+ vb_filter_v1_g [g][h] = thiscolg;
+
+ }
+ }
+
+}
+
+
+static void banshee_overlay_draw(svga_t *svga, int displine)
+{
+ banshee_t *banshee = (banshee_t *)svga->p;
+ voodoo_t *voodoo = banshee->voodoo;
+ uint32_t *p;
+ int x;
+ int y = voodoo->overlay.src_y >> 20;
+ uint32_t src_addr = svga->overlay_latch.addr + ((banshee->vidProcCfg & VIDPROCCFG_OVERLAY_TILE) ?
+ ((y & 31) * 128 + (y >> 5) * svga->overlay_latch.pitch) :
+ y * svga->overlay_latch.pitch);
+ uint32_t src_addr2 = svga->overlay_latch.addr + ((banshee->vidProcCfg & VIDPROCCFG_OVERLAY_TILE) ?
+ (((y + 1) & 31) * 128 + ((y + 1) >> 5) * svga->overlay_latch.pitch) :
+ (y + 1) * svga->overlay_latch.pitch);
+ uint8_t *src = &svga->vram[src_addr & svga->vram_mask];
+ uint32_t src_x = 0;
+ unsigned int y_coeff = (voodoo->overlay.src_y & 0xfffff) >> 4;
+ int skip_filtering;
+ uint32_t *clut = &svga->pallook[(banshee->vidProcCfg & VIDPROCCFG_OVERLAY_CLUT_SEL) ? 256 : 0];
+
+ if (svga->render == svga_render_null &&
+ !svga->changedvram[src_addr >> 12] && !svga->changedvram[src_addr2 >> 12] &&
+ !svga->fullchange &&
+ ((voodoo->overlay.src_y >> 20) < 2048 && !voodoo->dirty_line[voodoo->overlay.src_y >> 20]) &&
+ !(banshee->vidProcCfg & VIDPROCCFG_V_SCALE_ENABLE))
+ {
+ voodoo->overlay.src_y += (1 << 20);
+ return;
+ }
+
+ if ((voodoo->overlay.src_y >> 20) < 2048)
+ voodoo->dirty_line[voodoo->overlay.src_y >> 20] = 0;
+// pclog("displine=%i addr=%08x %08x %08x %08x\n", displine, svga->overlay_latch.addr, src_addr, voodoo->overlay.vidOverlayDvdy, *(uint32_t *)src);
+// if (src_addr >= 0x800000)
+// fatal("overlay out of range!\n");
+ p = &((uint32_t *)buffer32->line[displine])[svga->overlay_latch.x + 32];
+
+ if (banshee->voodoo->scrfilter && banshee->voodoo->scrfilterEnabled)
+ skip_filtering = ((banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_MASK) != VIDPROCCFG_FILTER_MODE_BILINEAR &&
+ !(banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) && !(banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_DITHER_4X4) &&
+ !(banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_DITHER_2X2));
+ else
+ skip_filtering = ((banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_MASK) != VIDPROCCFG_FILTER_MODE_BILINEAR &&
+ !(banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE));
+
+ if (skip_filtering)
+ {
+ /*No scaling or filtering required, just write straight to output buffer*/
+ OVERLAY_SAMPLE(p);
+ }
+ else
+ {
+ OVERLAY_SAMPLE(banshee->overlay_buffer[0]);
+
+ switch (banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_MASK)
+ {
+ case VIDPROCCFG_FILTER_MODE_BILINEAR:
+ src = &svga->vram[src_addr2 & svga->vram_mask];
+ OVERLAY_SAMPLE(banshee->overlay_buffer[1]);
+ if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE)
+ {
+ for (x = 0; x < svga->overlay_latch.xsize; x++)
+ {
+ unsigned int x_coeff = (src_x & 0xfffff) >> 4;
+ unsigned int coeffs[4] = {
+ ((0x10000 - x_coeff) * (0x10000 - y_coeff)) >> 16,
+ ( x_coeff * (0x10000 - y_coeff)) >> 16,
+ ((0x10000 - x_coeff) * y_coeff) >> 16,
+ ( x_coeff * y_coeff) >> 16
+ };
+ uint32_t samp0 = banshee->overlay_buffer[0][src_x >> 20];
+ uint32_t samp1 = banshee->overlay_buffer[0][(src_x >> 20) + 1];
+ uint32_t samp2 = banshee->overlay_buffer[1][src_x >> 20];
+ uint32_t samp3 = banshee->overlay_buffer[1][(src_x >> 20) + 1];
+ int r = (((samp0 >> 16) & 0xff) * coeffs[0] +
+ ((samp1 >> 16) & 0xff) * coeffs[1] +
+ ((samp2 >> 16) & 0xff) * coeffs[2] +
+ ((samp3 >> 16) & 0xff) * coeffs[3]) >> 16;
+ int g = (((samp0 >> 8) & 0xff) * coeffs[0] +
+ ((samp1 >> 8) & 0xff) * coeffs[1] +
+ ((samp2 >> 8) & 0xff) * coeffs[2] +
+ ((samp3 >> 8) & 0xff) * coeffs[3]) >> 16;
+ int b = ((samp0 & 0xff) * coeffs[0] +
+ (samp1 & 0xff) * coeffs[1] +
+ (samp2 & 0xff) * coeffs[2] +
+ (samp3 & 0xff) * coeffs[3]) >> 16;
+ p[x] = (r << 16) | (g << 8) | b;
+
+ src_x += voodoo->overlay.vidOverlayDudx;
+ }
+ }
+ else
+ {
+ for (x = 0; x < svga->overlay_latch.xsize; x++)
+ {
+ uint32_t samp0 = banshee->overlay_buffer[0][src_x >> 20];
+ uint32_t samp1 = banshee->overlay_buffer[1][src_x >> 20];
+ int r = (((samp0 >> 16) & 0xff) * (0x10000 - y_coeff) +
+ ((samp1 >> 16) & 0xff) * y_coeff) >> 16;
+ int g = (((samp0 >> 8) & 0xff) * (0x10000 - y_coeff) +
+ ((samp1 >> 8) & 0xff) * y_coeff) >> 16;
+ int b = ((samp0 & 0xff) * (0x10000 - y_coeff) +
+ (samp1 & 0xff) * y_coeff) >> 16;
+ p[x] = (r << 16) | (g << 8) | b;
+ }
+ }
+ break;
+
+ case VIDPROCCFG_FILTER_MODE_DITHER_4X4:
+ if (banshee->voodoo->scrfilter && banshee->voodoo->scrfilterEnabled)
+ {
+ uint8_t fil[(svga->overlay_latch.xsize) * 3];
+ uint8_t fil3[(svga->overlay_latch.xsize) * 3];
+
+ if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) /* leilei HACK - don't know of real 4x1 hscaled behavior yet, double for now */
+ {
+ for (x=0; xoverlay_latch.xsize;x++)
+ {
+ fil[x*3] = ((banshee->overlay_buffer[0][src_x >> 20]));
+ fil[x*3+1] = ((banshee->overlay_buffer[0][src_x >> 20] >> 8));
+ fil[x*3+2] = ((banshee->overlay_buffer[0][src_x >> 20] >> 16));
+ fil3[x*3+0] = fil[x*3+0];
+ fil3[x*3+1] = fil[x*3+1];
+ fil3[x*3+2] = fil[x*3+2];
+ src_x += voodoo->overlay.vidOverlayDudx;
+ }
+ }
+ else
+ {
+ for (x=0; xoverlay_latch.xsize;x++)
+ {
+ fil[x*3] = ((banshee->overlay_buffer[0][x]));
+ fil[x*3+1] = ((banshee->overlay_buffer[0][x] >> 8));
+ fil[x*3+2] = ((banshee->overlay_buffer[0][x] >> 16));
+ fil3[x*3+0] = fil[x*3+0];
+ fil3[x*3+1] = fil[x*3+1];
+ fil3[x*3+2] = fil[x*3+2];
+ }
+ }
+ if (y % 2 == 0)
+ {
+ for (x=0; xoverlay_latch.xsize;x++)
+ {
+ fil[x*3] = banshee->voodoo->purpleline[fil[x*3+0]][0];
+ fil[x*3+1] = banshee->voodoo->purpleline[fil[x*3+1]][1];
+ fil[x*3+2] = banshee->voodoo->purpleline[fil[x*3+2]][2];
+ }
+ }
+
+ for (x=1; xoverlay_latch.xsize;x++)
+ {
+ fil3[(x)*3] = vb_filter_v1_rb [fil[x*3]] [fil[(x-1) *3]];
+ fil3[(x)*3+1] = vb_filter_v1_g [fil[x*3+1]][fil[(x-1) *3+1]];
+ fil3[(x)*3+2] = vb_filter_v1_rb [fil[x*3+2]] [fil[(x-1) *3+2]];
+ }
+ for (x=1; xoverlay_latch.xsize;x++)
+ {
+ fil[(x)*3] = vb_filter_v1_rb [fil[x*3]] [fil3[(x-1) *3]];
+ fil[(x)*3+1] = vb_filter_v1_g [fil[x*3+1]][fil3[(x-1) *3+1]];
+ fil[(x)*3+2] = vb_filter_v1_rb [fil[x*3+2]] [fil3[(x-1) *3+2]];
+ }
+ for (x=1; xoverlay_latch.xsize;x++)
+ {
+ fil3[(x)*3] = vb_filter_v1_rb [fil[x*3]] [fil[(x-1) *3]];
+ fil3[(x)*3+1] = vb_filter_v1_g [fil[x*3+1]][fil[(x-1) *3+1]];
+ fil3[(x)*3+2] = vb_filter_v1_rb [fil[x*3+2]] [fil[(x-1) *3+2]];
+ }
+ for (x=0; xoverlay_latch.xsize;x++)
+ {
+ fil[(x)*3] = vb_filter_v1_rb [fil[x*3]] [fil3[(x+1) *3]];
+ fil[(x)*3+1] = vb_filter_v1_g [fil[x*3+1]][fil3[(x+1) *3+1]];
+ fil[(x)*3+2] = vb_filter_v1_rb [fil[x*3+2]] [fil3[(x+1) *3+2]];
+ p[x] = (fil[x*3+2] << 16) | (fil[x*3+1] << 8) | fil[x*3];
+ }
+ }
+ else /* filter disabled by emulator option */
+ {
+ if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE)
+ {
+ for (x = 0; x < svga->overlay_latch.xsize; x++)
+ {
+ p[x] = banshee->overlay_buffer[0][src_x >> 20];
+ src_x += voodoo->overlay.vidOverlayDudx;
+ }
+ }
+ else
+ {
+ for (x = 0; x < svga->overlay_latch.xsize; x++)
+ p[x] = banshee->overlay_buffer[0][x];
+ }
+ }
+ break;
+
+ case VIDPROCCFG_FILTER_MODE_DITHER_2X2:
+ if (banshee->voodoo->scrfilter && banshee->voodoo->scrfilterEnabled)
+ {
+ uint8_t fil[(svga->overlay_latch.xsize) * 3];
+ uint8_t soak[(svga->overlay_latch.xsize) * 3];
+ uint8_t soak2[(svga->overlay_latch.xsize) * 3];
+
+ uint8_t samp1[(svga->overlay_latch.xsize) * 3];
+ uint8_t samp2[(svga->overlay_latch.xsize) * 3];
+ uint8_t samp3[(svga->overlay_latch.xsize) * 3];
+ uint8_t samp4[(svga->overlay_latch.xsize) * 3];
+
+ src = &svga->vram[src_addr2 & svga->vram_mask];
+ OVERLAY_SAMPLE(banshee->overlay_buffer[1]);
+ for (x=0; xoverlay_latch.xsize;x++)
+ {
+ samp1[x*3] = ((banshee->overlay_buffer[0][x]));
+ samp1[x*3+1] = ((banshee->overlay_buffer[0][x] >> 8));
+ samp1[x*3+2] = ((banshee->overlay_buffer[0][x] >> 16));
+
+ samp2[x*3+0] = ((banshee->overlay_buffer[0][x+1]));
+ samp2[x*3+1] = ((banshee->overlay_buffer[0][x+1] >> 8));
+ samp2[x*3+2] = ((banshee->overlay_buffer[0][x+1] >> 16));
+
+ samp3[x*3+0] = ((banshee->overlay_buffer[1][x]));
+ samp3[x*3+1] = ((banshee->overlay_buffer[1][x] >> 8));
+ samp3[x*3+2] = ((banshee->overlay_buffer[1][x] >> 16));
+
+ samp4[x*3+0] = ((banshee->overlay_buffer[1][x+1]));
+ samp4[x*3+1] = ((banshee->overlay_buffer[1][x+1] >> 8));
+ samp4[x*3+2] = ((banshee->overlay_buffer[1][x+1] >> 16));
+
+ /* sample two lines */
+
+ soak[x*3+0] = vb_filter_bx_rb [samp1[x*3+0]] [samp2[x*3+0]];
+ soak[x*3+1] = vb_filter_bx_g [samp1[x*3+1]] [samp2[x*3+1]];
+ soak[x*3+2] = vb_filter_bx_rb [samp1[x*3+2]] [samp2[x*3+2]];
+
+ soak2[x*3+0] = vb_filter_bx_rb[samp3[x*3+0]] [samp4[x*3+0]];
+ soak2[x*3+1] = vb_filter_bx_g [samp3[x*3+1]] [samp4[x*3+1]];
+ soak2[x*3+2] = vb_filter_bx_rb[samp3[x*3+2]] [samp4[x*3+2]];
+
+ /* then pour it on the rest */
+
+ fil[x*3+0] = vb_filter_v1_rb[soak[x*3+0]] [soak2[x*3+0]];
+ fil[x*3+1] = vb_filter_v1_g [soak[x*3+1]] [soak2[x*3+1]];
+ fil[x*3+2] = vb_filter_v1_rb[soak[x*3+2]] [soak2[x*3+2]];
+ }
+
+ if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE) /* 2x2 on a scaled low res */
+ {
+ for (x=0; xoverlay_latch.xsize;x++)
+ {
+ p[x] = (fil[(src_x >> 20)*3+2] << 16) | (fil[(src_x >> 20)*3+1] << 8) | fil[(src_x >> 20)*3];
+ src_x += voodoo->overlay.vidOverlayDudx;
+ }
+ }
+ else
+ {
+ for (x=0; xoverlay_latch.xsize;x++)
+ {
+ p[x] = (fil[x*3+2] << 16) | (fil[x*3+1] << 8) | fil[x*3];
+ }
+ }
+ }
+ else /* filter disabled by emulator option */
+ {
+ if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE)
+ {
+ for (x = 0; x < svga->overlay_latch.xsize; x++)
+ {
+ p[x] = banshee->overlay_buffer[0][src_x >> 20];
+
+ src_x += voodoo->overlay.vidOverlayDudx;
+ }
+ }
+ else
+ {
+ for (x = 0; x < svga->overlay_latch.xsize; x++)
+ p[x] = banshee->overlay_buffer[0][x];
+ }
+ }
+ break;
+
+ case VIDPROCCFG_FILTER_MODE_POINT:
+ default:
+ if (banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE)
+ {
+ for (x = 0; x < svga->overlay_latch.xsize; x++)
+ {
+ p[x] = banshee->overlay_buffer[0][src_x >> 20];
+
+ src_x += voodoo->overlay.vidOverlayDudx;
+ }
+ }
+ else
+ {
+ for (x = 0; x < svga->overlay_latch.xsize; x++)
+ p[x] = banshee->overlay_buffer[0][x];
+ }
+ break;
+ }
+ }
+
+ if (banshee->vidProcCfg & VIDPROCCFG_V_SCALE_ENABLE)
+ voodoo->overlay.src_y += voodoo->overlay.vidOverlayDvdy;
+ else
+ voodoo->overlay.src_y += (1 << 20);
+}
+
+void banshee_set_overlay_addr(void *p, uint32_t addr)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ voodoo_t *voodoo = banshee->voodoo;
+
+ banshee->svga.overlay.addr = banshee->voodoo->leftOverlayBuf & 0xfffffff;
+ banshee->svga.overlay_latch.addr = banshee->voodoo->leftOverlayBuf & 0xfffffff;
+ memset(voodoo->dirty_line, 1, sizeof(voodoo->dirty_line));
+}
+
+static void banshee_vsync_callback(svga_t *svga)
+{
+ banshee_t *banshee = (banshee_t *)svga->p;
+ voodoo_t *voodoo = banshee->voodoo;
+
+ voodoo->retrace_count++;
+ thread_lock_mutex(voodoo->swap_mutex);
+ if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval))
+ {
+ if (voodoo->swap_count > 0)
+ voodoo->swap_count--;
+ voodoo->swap_pending = 0;
+ thread_unlock_mutex(voodoo->swap_mutex);
+
+ memset(voodoo->dirty_line, 1, sizeof(voodoo->dirty_line));
+ voodoo->retrace_count = 0;
+ banshee_set_overlay_addr(banshee, voodoo->swap_offset);
+ thread_set_event(voodoo->wake_fifo_thread);
+ voodoo->frame_count++;
+ }
+ else
+ thread_unlock_mutex(voodoo->swap_mutex);
+
+ voodoo->overlay.src_y = 0;
+ banshee->desktop_addr = banshee->vidDesktopStartAddr;
+ banshee->desktop_y = 0;
+}
+
+static uint8_t banshee_pci_read(int func, int addr, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+// svga_t *svga = &banshee->svga;
+ uint8_t ret = 0;
+
+ if (func)
+ return 0xff;
+// pclog("Banshee PCI read %08X ", addr);
+ switch (addr)
+ {
+ case 0x00: ret = 0x1a; break; /*3DFX*/
+ case 0x01: ret = 0x12; break;
+
+ case 0x02: ret = (banshee->type == TYPE_BANSHEE) ? 0x03 : 0x05; break;
+ case 0x03: ret = 0x00; break;
+
+ case 0x04: ret = banshee->pci_regs[0x04] & 0x27; break;
+
+ case 0x07: ret = banshee->pci_regs[0x07] & 0x36; break;
+
+ case 0x08: ret = (banshee->type == TYPE_BANSHEE) ? 3 : 1; break; /*Revision ID*/
+ case 0x09: ret = 0; break; /*Programming interface*/
+
+ case 0x0a: ret = 0x00; break; /*Supports VGA interface*/
+ case 0x0b: ret = 0x03; /*output = 3; */break;
+
+ case 0x0d: ret = banshee->pci_regs[0x0d] & 0xf8; break;
+
+ case 0x10: ret = 0x00; break; /*memBaseAddr0*/
+ case 0x11: ret = 0x00; break;
+ case 0x12: ret = 0x00; break;
+ case 0x13: ret = banshee->memBaseAddr0 >> 24; break;
+
+ case 0x14: ret = 0x00; break; /*memBaseAddr1*/
+ case 0x15: ret = 0x00; break;
+ case 0x16: ret = 0x00; break;
+ case 0x17: ret = banshee->memBaseAddr1 >> 24; break;
+
+ case 0x18: ret = 0x01; break; /*ioBaseAddr*/
+ case 0x19: ret = banshee->ioBaseAddr >> 8; break;
+ case 0x1a: ret = 0x00; break;
+ case 0x1b: ret = 0x00; break;
+
+ /*Subsystem vendor ID*/
+ case 0x2c: ret = banshee->pci_regs[0x2c]; break;
+ case 0x2d: ret = banshee->pci_regs[0x2d]; break;
+ case 0x2e: ret = banshee->pci_regs[0x2e]; break;
+ case 0x2f: ret = banshee->pci_regs[0x2f]; break;
+
+ case 0x30: ret = banshee->pci_regs[0x30] & 0x01; break; /*BIOS ROM address*/
+ case 0x31: ret = 0x00; break;
+ case 0x32: ret = banshee->pci_regs[0x32]; break;
+ case 0x33: ret = banshee->pci_regs[0x33]; break;
+
+ case 0x3c: ret = banshee->pci_regs[0x3c]; break;
+
+ case 0x3d: ret = 0x01; break; /*INTA*/
+
+ case 0x3e: ret = 0x04; break;
+ case 0x3f: ret = 0xff; break;
+
+ }
+// pclog("%02X\n", ret);
+ return ret;
+}
+
+static void banshee_pci_write(int func, int addr, uint8_t val, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+// svga_t *svga = &banshee->svga;
+
+ if (func)
+ return;
+// pclog("Banshee write %08X %02X %04X:%08X\n", addr, val, CS, cpu_state.pc);
+ switch (addr)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ case 0x3d: case 0x3e: case 0x3f:
+ return;
+
+ case PCI_REG_COMMAND:
+ if (val & PCI_COMMAND_IO)
+ {
+ io_removehandler(0x03c0, 0x0020, banshee_in, NULL, NULL, banshee_out, NULL, NULL, banshee);
+ if (banshee->ioBaseAddr)
+ io_removehandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee);
+
+ io_sethandler(0x03c0, 0x0020, banshee_in, NULL, NULL, banshee_out, NULL, NULL, banshee);
+ if (banshee->ioBaseAddr)
+ io_sethandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee);
+ }
+ else
+ {
+ io_removehandler(0x03c0, 0x0020, banshee_in, NULL, NULL, banshee_out, NULL, NULL, banshee);
+ io_removehandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee);
+ }
+ banshee->pci_regs[PCI_REG_COMMAND] = val & 0x27;
+ banshee_updatemapping(banshee);
+ return;
+ case 0x07:
+ banshee->pci_regs[0x07] = val & 0x3e;
+ return;
+ case 0x0d:
+ banshee->pci_regs[0x0d] = val & 0xf8;
+ return;
+
+ case 0x13:
+ banshee->memBaseAddr0 = (val & 0xfe) << 24;
+ banshee_updatemapping(banshee);
+ return;
+
+ case 0x17:
+ banshee->memBaseAddr1 = (val & 0xfe) << 24;
+ banshee_updatemapping(banshee);
+ return;
+
+ case 0x19:
+ if (banshee->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO)
+ io_removehandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee);
+ banshee->ioBaseAddr = val << 8;
+ if ((banshee->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && banshee->ioBaseAddr)
+ io_sethandler(banshee->ioBaseAddr, 0x0100, banshee_ext_in, NULL, banshee_ext_inl, banshee_ext_out, NULL, banshee_ext_outl, banshee);
+ pclog("Banshee ioBaseAddr=%08x\n", banshee->ioBaseAddr);
+// s3_virge_updatemapping(virge);
+ return;
+
+ case 0x30: case 0x32: case 0x33:
+ banshee->pci_regs[addr] = val;
+ if (banshee->pci_regs[0x30] & 0x01)
+ {
+ uint32_t addr = (banshee->pci_regs[0x32] << 16) | (banshee->pci_regs[0x33] << 24);
+ pclog("Banshee bios_rom enabled at %08x\n", addr);
+ mem_mapping_set_addr(&banshee->bios_rom.mapping, addr, 0x10000);
+ mem_mapping_enable(&banshee->bios_rom.mapping);
+ }
+ else
+ {
+ pclog("Banshee bios_rom disabled\n");
+ mem_mapping_disable(&banshee->bios_rom.mapping);
+ }
+ return;
+ case 0x3c:
+ banshee->pci_regs[0x3c] = val;
+ return;
+ }
+}
+
+static device_config_t banshee_sgram_config[] =
+{
+ {
+ .name = "memory",
+ .description = "Memory size",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "8 MB",
+ .value = 8
+ },
+ {
+ .description = "16 MB",
+ .value = 16
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 16
+ },
+ {
+ .name = "bilinear",
+ .description = "Bilinear filtering",
+ .type = CONFIG_BINARY,
+ .default_int = 1
+ },
+ {
+ .name = "dithersub",
+ .description = "Dither subtraction",
+ .type = CONFIG_BINARY,
+ .default_int = 1
+ },
+ {
+ .name = "dacfilter",
+ .description = "Screen Filter",
+ .type = CONFIG_BINARY,
+ .default_int = 0
+ },
+ {
+ .name = "render_threads",
+ .description = "Render threads",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "1",
+ .value = 1
+ },
+ {
+ .description = "2",
+ .value = 2
+ },
+ {
+ .description = "4",
+ .value = 4
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 2
+ },
+#ifndef NO_CODEGEN
+ {
+ .name = "recompiler",
+ .description = "Recompiler",
+ .type = CONFIG_BINARY,
+ .default_int = 1
+ },
+#endif
+ {
+ .type = -1
+ }
+};
+
+static device_config_t banshee_sdram_config[] =
+{
+ {
+ .name = "bilinear",
+ .description = "Bilinear filtering",
+ .type = CONFIG_BINARY,
+ .default_int = 1
+ },
+ {
+ .name = "dithersub",
+ .description = "Dither subtraction",
+ .type = CONFIG_BINARY,
+ .default_int = 1
+ },
+ {
+ .name = "dacfilter",
+ .description = "Screen Filter",
+ .type = CONFIG_BINARY,
+ .default_int = 0
+ },
+ {
+ .name = "render_threads",
+ .description = "Render threads",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "1",
+ .value = 1
+ },
+ {
+ .description = "2",
+ .value = 2
+ },
+ {
+ .description = "4",
+ .value = 4
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 2
+ },
+#ifndef NO_CODEGEN
+ {
+ .name = "recompiler",
+ .description = "Recompiler",
+ .type = CONFIG_BINARY,
+ .default_int = 1
+ },
+#endif
+ {
+ .type = -1
+ }
+};
+
+static void *banshee_init_common(char *fn, int has_sgram, int type, int voodoo_type)
+{
+ int mem_size;
+ banshee_t *banshee = malloc(sizeof(banshee_t));
+ memset(banshee, 0, sizeof(banshee_t));
+
+ banshee->type = type;
+
+ rom_init(&banshee->bios_rom, fn, 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL);
+ mem_mapping_disable(&banshee->bios_rom.mapping);
+
+ if (has_sgram)
+ mem_size = device_get_config_int("memory");
+ else
+ mem_size = 16; /*SDRAM Banshee only supports 16 MB*/
+
+ svga_init(&banshee->svga, banshee, mem_size << 20,
+ banshee_recalctimings,
+ banshee_in, banshee_out,
+ banshee_hwcursor_draw,
+ banshee_overlay_draw);
+ banshee->svga.vsync_callback = banshee_vsync_callback;
+
+ mem_mapping_add(&banshee->linear_mapping, 0, 0, banshee_read_linear,
+ banshee_read_linear_w,
+ banshee_read_linear_l,
+ banshee_write_linear,
+ banshee_write_linear_w,
+ banshee_write_linear_l,
+ NULL,
+ MEM_MAPPING_EXTERNAL,
+ &banshee->svga);
+ mem_mapping_add(&banshee->reg_mapping_low, 0, 0,banshee_reg_read,
+ banshee_reg_readw,
+ banshee_reg_readl,
+ banshee_reg_write,
+ banshee_reg_writew,
+ banshee_reg_writel,
+ NULL,
+ MEM_MAPPING_EXTERNAL,
+ banshee);
+ mem_mapping_add(&banshee->reg_mapping_high, 0,0,banshee_reg_read,
+ banshee_reg_readw,
+ banshee_reg_readl,
+ banshee_reg_write,
+ banshee_reg_writew,
+ banshee_reg_writel,
+ NULL,
+ MEM_MAPPING_EXTERNAL,
+ banshee);
+
+// io_sethandler(0x03c0, 0x0020, banshee_in, NULL, NULL, banshee_out, NULL, NULL, banshee);
+
+ banshee->svga.bpp = 8;
+ banshee->svga.miscout = 1;
+
+ banshee->dramInit0 = 1 << 27;
+ if (has_sgram && mem_size == 16)
+ banshee->dramInit0 |= (1 << 26); /*2xSGRAM = 16 MB*/
+ if (!has_sgram)
+ banshee->dramInit1 = 1 << 30; /*SDRAM*/
+ banshee->svga.decode_mask = 0x1ffffff;
+
+ pci_add(banshee_pci_read, banshee_pci_write, banshee);
+
+ banshee->voodoo = voodoo_2d3d_card_init(voodoo_type);
+ banshee->voodoo->p = banshee;
+ banshee->voodoo->vram = banshee->svga.vram;
+ banshee->voodoo->changedvram = banshee->svga.changedvram;
+ banshee->voodoo->fb_mem = banshee->svga.vram;
+ banshee->voodoo->fb_mask = banshee->svga.vram_mask;
+ banshee->voodoo->tex_mem[0] = banshee->svga.vram;
+ banshee->voodoo->tex_mem_w[0] = (uint16_t *)banshee->svga.vram;
+ banshee->voodoo->tex_mem[1] = banshee->svga.vram;
+ banshee->voodoo->tex_mem_w[1] = (uint16_t *)banshee->svga.vram;
+ banshee->voodoo->texture_mask = banshee->svga.vram_mask;
+ voodoo_generate_filter_v1(banshee->voodoo);
+
+ banshee->vidSerialParallelPort = VIDSERIAL_DDC_DCK_W | VIDSERIAL_DDC_DDA_W;
+
+ ddc_init();
+
+ switch (type)
+ {
+ case TYPE_BANSHEE:
+ if (has_sgram)
+ {
+ banshee->pci_regs[0x2c] = 0x1a;
+ banshee->pci_regs[0x2d] = 0x12;
+ banshee->pci_regs[0x2e] = 0x04;
+ banshee->pci_regs[0x2f] = 0x00;
+ }
+ else
+ {
+ banshee->pci_regs[0x2c] = 0x02;
+ banshee->pci_regs[0x2d] = 0x11;
+ banshee->pci_regs[0x2e] = 0x17;
+ banshee->pci_regs[0x2f] = 0x10;
+ }
+ break;
+
+ case TYPE_V3_2000:
+ banshee->pci_regs[0x2c] = 0x1a;
+ banshee->pci_regs[0x2d] = 0x12;
+ banshee->pci_regs[0x2e] = 0x30;
+ banshee->pci_regs[0x2f] = 0x00;
+ break;
+
+ case TYPE_V3_3000:
+ banshee->pci_regs[0x2c] = 0x1a;
+ banshee->pci_regs[0x2d] = 0x12;
+ banshee->pci_regs[0x2e] = 0x3a;
+ banshee->pci_regs[0x2f] = 0x00;
+ break;
+ }
+
+ return banshee;
+}
+
+static void *banshee_init()
+{
+ return banshee_init_common("pci_sg.rom", 1, TYPE_BANSHEE, VOODOO_BANSHEE);
+}
+static void *creative_banshee_init()
+{
+ return banshee_init_common("blasterpci.rom", 0, TYPE_BANSHEE, VOODOO_BANSHEE);
+}
+static void *v3_2000_init()
+{
+ return banshee_init_common("voodoo3_2000/2k11sd.rom", 0, TYPE_V3_2000, VOODOO_3);
+}
+static void *v3_3000_init()
+{
+ return banshee_init_common("voodoo3_3000/3k12sd.rom", 0, TYPE_V3_3000, VOODOO_3);
+}
+
+static int banshee_available()
+{
+ return rom_present("pci_sg.rom");
+}
+static int creative_banshee_available()
+{
+ return rom_present("blasterpci.rom");
+}
+static int v3_2000_available()
+{
+ return rom_present("voodoo3_2000/2k11sd.rom");
+}
+static int v3_3000_available()
+{
+ return rom_present("voodoo3_3000/3k12sd.rom");
+}
+
+static void banshee_close(void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+
+ voodoo_card_close(banshee->voodoo);
+ svga_close(&banshee->svga);
+
+ free(banshee);
+}
+
+static void banshee_speed_changed(void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+
+ svga_recalctimings(&banshee->svga);
+}
+
+static void banshee_force_redraw(void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+
+ banshee->svga.fullchange = changeframecount;
+}
+
+static uint64_t status_time = 0;
+
+static void banshee_add_status_info(char *s, int max_len, void *p)
+{
+ banshee_t *banshee = (banshee_t *)p;
+ voodoo_t *voodoo = banshee->voodoo;
+ char temps[512];
+ int pixel_count_current[4];
+ int pixel_count_total;
+ int texel_count_current[4];
+ int texel_count_total;
+ int render_time[4];
+ uint64_t new_time = timer_read();
+ uint64_t status_diff = new_time - status_time;
+ int c;
+ status_time = new_time;
+
+ svga_add_status_info(s, max_len, &banshee->svga);
+
+
+ for (c = 0; c < 4; c++)
+ {
+ pixel_count_current[c] = voodoo->pixel_count[c];
+ texel_count_current[c] = voodoo->texel_count[c];
+ render_time[c] = voodoo->render_time[c];
+ }
+
+ pixel_count_total = (pixel_count_current[0] + pixel_count_current[1] + pixel_count_current[2] + pixel_count_current[3]) -
+ (voodoo->pixel_count_old[0] + voodoo->pixel_count_old[1] + voodoo->pixel_count_old[2] + voodoo->pixel_count_old[3]);
+ texel_count_total = (texel_count_current[0] + texel_count_current[1] + texel_count_current[2] + texel_count_current[3]) -
+ (voodoo->texel_count_old[0] + voodoo->texel_count_old[1] + voodoo->texel_count_old[2] + voodoo->texel_count_old[3]);
+ sprintf(temps, "%f Mpixels/sec (%f)\n%f Mtexels/sec (%f)\n%f ktris/sec\n%f%% CPU (%f%% real)\n%d frames/sec (%i)\n%f%% CPU (%f%% real)\n"/*%d reads/sec\n%d write/sec\n%d tex/sec\n*/,
+ (double)pixel_count_total/1000000.0,
+ ((double)pixel_count_total/1000000.0) / ((double)render_time[0] / status_diff),
+ (double)texel_count_total/1000000.0,
+ ((double)texel_count_total/1000000.0) / ((double)render_time[0] / status_diff),
+ (double)voodoo->tri_count/1000.0, ((double)voodoo->time * 100.0) / timer_freq, ((double)voodoo->time * 100.0) / status_diff, voodoo->frame_count, voodoo_recomp,
+ ((double)voodoo->render_time[0] * 100.0) / timer_freq, ((double)voodoo->render_time[0] * 100.0) / status_diff);
+ if (voodoo->render_threads >= 2)
+ {
+ char temps2[512];
+ sprintf(temps2, "%f%% CPU (%f%% real)\n",
+ ((double)voodoo->render_time[1] * 100.0) / timer_freq, ((double)voodoo->render_time[1] * 100.0) / status_diff);
+ strncat(temps, temps2, sizeof(temps)-1);
+ }
+ if (voodoo->render_threads == 4)
+ {
+ char temps2[512];
+ sprintf(temps2, "%f%% CPU (%f%% real)\n%f%% CPU (%f%% real)\n",
+ ((double)voodoo->render_time[2] * 100.0) / timer_freq, ((double)voodoo->render_time[2] * 100.0) / status_diff,
+ ((double)voodoo->render_time[3] * 100.0) / timer_freq, ((double)voodoo->render_time[3] * 100.0) / status_diff);
+ strncat(temps, temps2, sizeof(temps)-1);
+ }
+
+ strncat(s, temps, max_len);
+
+ strncat(s, "Overlay mode: ", max_len); /* leilei debug additions */
+ if ((banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_MASK) == VIDPROCCFG_FILTER_MODE_DITHER_2X2)
+ strncat(s, "2x2 box filter\n", max_len);
+ if ((banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_MASK) == VIDPROCCFG_FILTER_MODE_DITHER_4X4)
+ strncat(s, "4x1 tap filter\n", max_len);
+ if ((banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_MASK) == VIDPROCCFG_FILTER_MODE_POINT)
+ strncat(s, "Nearest neighbor\n", max_len);
+ if ((banshee->vidProcCfg & VIDPROCCFG_FILTER_MODE_MASK) == VIDPROCCFG_FILTER_MODE_BILINEAR)
+ strncat(s, "Bilinear filtered\n", max_len);
+ if ((banshee->vidProcCfg & VIDPROCCFG_H_SCALE_ENABLE))
+ strncat(s, "H scaled \n", max_len);
+ if ((banshee->vidProcCfg & VIDPROCCFG_V_SCALE_ENABLE))
+ strncat(s, "V scaled \n", max_len);
+ if ((banshee->vidProcCfg & VIDPROCCFG_2X_MODE))
+ strncat(s, "2X mode\n", max_len);
+
+ strncat(s, "\n", max_len);
+
+ for (c = 0; c < 4; c++)
+ {
+ voodoo->pixel_count_old[c] = pixel_count_current[c];
+ voodoo->texel_count_old[c] = texel_count_current[c];
+ voodoo->render_time[c] = 0;
+ }
+
+ voodoo->tri_count = voodoo->frame_count = 0;
+ voodoo->rd_count = voodoo->wr_count = voodoo->tex_count = 0;
+ voodoo->time = 0;
+
+ voodoo->read_time = pci_nonburst_time + pci_burst_time;
+
+ voodoo_recomp = 0;
+}
+
+device_t voodoo_banshee_device =
+{
+ "Voodoo Banshee PCI (reference)",
+ DEVICE_PCI,
+ banshee_init,
+ banshee_close,
+ banshee_available,
+ banshee_speed_changed,
+ banshee_force_redraw,
+ banshee_add_status_info,
+ banshee_sgram_config
+};
+
+device_t creative_voodoo_banshee_device =
+{
+ "Creative Labs 3D Blaster Banshee PCI",
+ DEVICE_PCI,
+ creative_banshee_init,
+ banshee_close,
+ creative_banshee_available,
+ banshee_speed_changed,
+ banshee_force_redraw,
+ banshee_add_status_info,
+ banshee_sdram_config
+};
+
+device_t voodoo_3_2000_device =
+{
+ "Voodoo 3 2000 PCI",
+ DEVICE_PCI,
+ v3_2000_init,
+ banshee_close,
+ v3_2000_available,
+ banshee_speed_changed,
+ banshee_force_redraw,
+ banshee_add_status_info,
+ banshee_sdram_config
+};
+
+device_t voodoo_3_3000_device =
+{
+ "Voodoo 3 3000 PCI",
+ DEVICE_PCI,
+ v3_3000_init,
+ banshee_close,
+ v3_3000_available,
+ banshee_speed_changed,
+ banshee_force_redraw,
+ banshee_add_status_info,
+ banshee_sdram_config
+};
diff --git a/src/vid_voodoo_banshee.h b/src/vid_voodoo_banshee.h
new file mode 100644
index 0000000..ddd7e3f
--- /dev/null
+++ b/src/vid_voodoo_banshee.h
@@ -0,0 +1,6 @@
+extern device_t voodoo_banshee_device;
+extern device_t creative_voodoo_banshee_device;
+extern device_t voodoo_3_2000_device;
+extern device_t voodoo_3_3000_device;
+
+void banshee_set_overlay_addr(void *p, uint32_t addr);
diff --git a/src/vid_voodoo_banshee_blitter.c b/src/vid_voodoo_banshee_blitter.c
new file mode 100644
index 0000000..f6f0d03
--- /dev/null
+++ b/src/vid_voodoo_banshee_blitter.c
@@ -0,0 +1,1450 @@
+/*Current issues :
+ - missing screen->screen scaled blits with format conversion
+ - missing YUV blits
+ - missing linestyle
+ - missing wait for vsync
+ - missing reversible lines
+
+ Notes :
+ - 16 bpp runs with tiled framebuffer - to aid 3D?
+ 8 and 32 bpp use linear
+*/
+#include
+#include
+#include "ibm.h"
+#include "device.h"
+#include "mem.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_svga.h"
+#include "vid_voodoo.h"
+#include "vid_voodoo_common.h"
+#include "vid_voodoo_banshee_blitter.h"
+#include "vid_voodoo_render.h"
+
+#define COMMAND_CMD_MASK (0xf)
+#define COMMAND_CMD_NOP (0 << 0)
+#define COMMAND_CMD_SCREEN_TO_SCREEN_BLT (1 << 0)
+#define COMMAND_CMD_SCREEN_TO_SCREEN_STRETCH_BLT (2 << 0)
+#define COMMAND_CMD_HOST_TO_SCREEN_BLT (3 << 0)
+#define COMMAND_CMD_HOST_TO_SCREEN_STRETCH_BLT (4 << 0)
+#define COMMAND_CMD_RECTFILL (5 << 0)
+#define COMMAND_CMD_LINE (6 << 0)
+#define COMMAND_CMD_POLYLINE (7 << 0)
+#define COMMAND_CMD_POLYFILL (8 << 0)
+#define COMMAND_INITIATE (1 << 8)
+#define COMMAND_INC_X_START (1 << 10)
+#define COMMAND_INC_Y_START (1 << 11)
+#define COMMAND_STIPPLE_LINE (1 << 12)
+#define COMMAND_PATTERN_MONO (1 << 13)
+#define COMMAND_DX (1 << 14)
+#define COMMAND_DY (1 << 15)
+#define COMMAND_TRANS_MONO (1 << 16)
+#define COMMAND_PATOFF_X_MASK (7 << 17)
+#define COMMAND_PATOFF_X_SHIFT (17)
+#define COMMAND_PATOFF_Y_MASK (7 << 20)
+#define COMMAND_PATOFF_Y_SHIFT (20)
+#define COMMAND_CLIP_SEL (1 << 23)
+
+#define CMDEXTRA_SRC_COLORKEY (1 << 0)
+#define CMDEXTRA_DST_COLORKEY (1 << 1)
+#define CMDEXTRA_FORCE_PAT_ROW0 (1 << 3)
+
+#define SRC_FORMAT_STRIDE_MASK (0x1fff)
+#define SRC_FORMAT_COL_MASK (0xf << 16)
+#define SRC_FORMAT_COL_1_BPP (0 << 16)
+#define SRC_FORMAT_COL_8_BPP (1 << 16)
+#define SRC_FORMAT_COL_16_BPP (3 << 16)
+#define SRC_FORMAT_COL_24_BPP (4 << 16)
+#define SRC_FORMAT_COL_32_BPP (5 << 16)
+#define SRC_FORMAT_COL_YUYV (8 << 16)
+#define SRC_FORMAT_COL_UYVY (9 << 16)
+#define SRC_FORMAT_BYTE_SWIZZLE (1 << 20)
+#define SRC_FORMAT_WORD_SWIZZLE (1 << 21)
+#define SRC_FORMAT_PACKING_MASK (3 << 22)
+#define SRC_FORMAT_PACKING_STRIDE (0 << 22)
+#define SRC_FORMAT_PACKING_BYTE (1 << 22)
+#define SRC_FORMAT_PACKING_WORD (2 << 22)
+#define SRC_FORMAT_PACKING_DWORD (3 << 22)
+
+#define DST_FORMAT_STRIDE_MASK (0x1fff)
+#define DST_FORMAT_COL_MASK (0xf << 16)
+#define DST_FORMAT_COL_8_BPP (1 << 16)
+#define DST_FORMAT_COL_16_BPP (3 << 16)
+#define DST_FORMAT_COL_24_BPP (4 << 16)
+#define DST_FORMAT_COL_32_BPP (5 << 16)
+
+#define BRES_ERROR_MASK (0xffff)
+#define BRES_ERROR_USE (1 << 31)
+
+enum
+{
+ COLORKEY_8,
+ COLORKEY_16,
+ COLORKEY_32
+};
+
+static int colorkey(voodoo_t *voodoo, uint32_t src, int src_notdst, int color_format)
+{
+ uint32_t min = src_notdst ? voodoo->banshee_blt.srcColorkeyMin : voodoo->banshee_blt.dstColorkeyMin;
+ uint32_t max = src_notdst ? voodoo->banshee_blt.srcColorkeyMax : voodoo->banshee_blt.dstColorkeyMax;
+
+ if (!(voodoo->banshee_blt.commandExtra & (src_notdst ? CMDEXTRA_SRC_COLORKEY : CMDEXTRA_DST_COLORKEY)))
+ return 0;
+
+ switch (color_format)
+ {
+ case COLORKEY_8:
+ return ((src & 0xff) >= (min & 0xff)) && ((src & 0xff) <= (max & 0xff));
+
+ case COLORKEY_16:
+ {
+ int r = (src >> 11) & 0x1f, r_min = (min >> 11) & 0x1f, r_max = (max >> 11) & 0x1f;
+ int g = (src >> 5) & 0x3f, g_min = (min >> 5) & 0x3f, g_max = (max >> 5) & 0x3f;
+ int b = src & 0x1f, b_min = min & 0x1f, b_max = max & 0x1f;
+
+ return (r >= r_min) && (r <= r_max) && (g >= g_min) && (g <= g_max) &&
+ (b >= b_min) && (b <= b_max);
+ }
+
+ case COLORKEY_32:
+ {
+ int r = (src >> 16) & 0xff, r_min = (min >> 16) & 0xff, r_max = (max >> 16) & 0xff;
+ int g = (src >> 8) & 0xff, g_min = (min >> 8) & 0xff, g_max = (max >> 8) & 0xff;
+ int b = src & 0xff, b_min = min & 0xff, b_max = max & 0xff;
+
+ return (r >= r_min) && (r <= r_max) && (g >= g_min) && (g <= g_max) &&
+ (b >= b_min) && (b <= b_max);
+ }
+
+ default:
+ return 0;
+ }
+}
+
+static uint32_t MIX(voodoo_t *voodoo, uint32_t dest, uint32_t src, uint32_t pattern, int colour_format_src, int colour_format_dest)
+{
+ int rop_nr = 0;
+ uint32_t result = 0;
+ uint32_t rop;
+
+ if (colorkey(voodoo, src, 1, colour_format_src))
+ rop_nr |= 2;
+ if (colorkey(voodoo, dest, 0, colour_format_dest))
+ rop_nr |= 1;
+
+ rop = voodoo->banshee_blt.rops[rop_nr];
+
+ if (rop & 0x01)
+ result |= (~pattern & ~src & ~dest);
+ if (rop & 0x02)
+ result |= (~pattern & ~src & dest);
+ if (rop & 0x04)
+ result |= (~pattern & src & ~dest);
+ if (rop & 0x08)
+ result |= (~pattern & src & dest);
+ if (rop & 0x10)
+ result |= ( pattern & ~src & ~dest);
+ if (rop & 0x20)
+ result |= ( pattern & ~src & dest);
+ if (rop & 0x40)
+ result |= ( pattern & src & ~dest);
+ if (rop & 0x80)
+ result |= ( pattern & src & dest);
+
+ return result;
+}
+
+static uint32_t get_addr(voodoo_t *voodoo, int x, int y, int src_notdst, uint32_t src_stride)
+{
+ uint32_t stride = src_notdst ? src_stride : voodoo->banshee_blt.dst_stride;
+ uint32_t base_addr = src_notdst ? voodoo->banshee_blt.srcBaseAddr : voodoo->banshee_blt.dstBaseAddr;
+
+ if (src_notdst ? voodoo->banshee_blt.srcBaseAddr_tiled : voodoo->banshee_blt.dstBaseAddr_tiled)
+ return (base_addr + (x & 127) + ((x >> 7) * 128*32) + ((y & 31) * 128) + (y >> 5)*stride) & voodoo->fb_mask;
+ else
+ return (base_addr + x + y*stride) & voodoo->fb_mask;
+}
+
+static void PLOT(voodoo_t *voodoo, int x, int y, int pat_x, int pat_y, uint8_t pattern_mask, uint8_t rop, uint32_t src, int src_colorkey)
+{
+ switch (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK)
+ {
+ case DST_FORMAT_COL_8_BPP:
+ {
+ uint32_t addr = get_addr(voodoo, x, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t dest = voodoo->vram[addr];
+ uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ?
+ ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) :
+ voodoo->banshee_blt.colorPattern8[(pat_x & 7) + (pat_y & 7)*8];
+
+ voodoo->vram[addr] = MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_8);
+ voodoo->changedvram[addr >> 12] = changeframecount;
+ break;
+ }
+ case DST_FORMAT_COL_16_BPP:
+ {
+ uint32_t addr = get_addr(voodoo, x*2, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x*2 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t dest = *(uint16_t *)&voodoo->vram[addr];
+ uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ?
+ ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) :
+ voodoo->banshee_blt.colorPattern16[(pat_x & 7) + (pat_y & 7)*8];
+
+ *(uint16_t *)&voodoo->vram[addr] = MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_16);
+ voodoo->changedvram[addr >> 12] = changeframecount;
+ break;
+ }
+ case DST_FORMAT_COL_24_BPP:
+ {
+ uint32_t addr = get_addr(voodoo, x*3, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x*3 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t dest = *(uint32_t *)&voodoo->vram[addr];
+ uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ?
+ ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) :
+ voodoo->banshee_blt.colorPattern24[(pat_x & 7) + (pat_y & 7)*8];
+
+ *(uint32_t *)&voodoo->vram[addr] = (MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_32) & 0xffffff) | (dest & 0xff000000);
+ voodoo->changedvram[addr >> 12] = changeframecount;
+ break;
+ }
+ case DST_FORMAT_COL_32_BPP:
+ {
+ uint32_t addr = get_addr(voodoo, x*4, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x*4 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t dest = *(uint32_t *)&voodoo->vram[addr];
+ uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ?
+ ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) :
+ voodoo->banshee_blt.colorPattern[(pat_x & 7) + (pat_y & 7)*8];
+
+ *(uint32_t *)&voodoo->vram[addr] = MIX(voodoo, dest, src, pattern, src_colorkey, COLORKEY_32);
+ voodoo->changedvram[addr >> 12] = changeframecount;
+ break;
+ }
+ }
+}
+
+static void PLOT_LINE(voodoo_t *voodoo, int x, int y, uint8_t rop, uint32_t pattern, int src_colorkey)
+{
+ switch (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK)
+ {
+ case DST_FORMAT_COL_8_BPP:
+ {
+ uint32_t addr = get_addr(voodoo, x, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t dest = voodoo->vram[addr];
+
+ voodoo->vram[addr] = MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_8);
+ voodoo->changedvram[addr >> 12] = changeframecount;
+ break;
+ }
+ case DST_FORMAT_COL_16_BPP:
+ {
+ uint32_t addr = get_addr(voodoo, x*2, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x*2 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t dest = *(uint16_t *)&voodoo->vram[addr];
+
+ *(uint16_t *)&voodoo->vram[addr] = MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_16);
+ voodoo->changedvram[addr >> 12] = changeframecount;
+ break;
+ }
+ case DST_FORMAT_COL_24_BPP:
+ {
+ uint32_t addr = get_addr(voodoo, x*3, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x*3 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t dest = *(uint32_t *)&voodoo->vram[addr];
+
+ *(uint32_t *)&voodoo->vram[addr] = (MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_32) & 0xffffff) | (dest & 0xff000000);
+ voodoo->changedvram[addr >> 12] = changeframecount;
+ break;
+ }
+ case DST_FORMAT_COL_32_BPP:
+ {
+ uint32_t addr = get_addr(voodoo, x*4, y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + x*4 + y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t dest = *(uint32_t *)&voodoo->vram[addr];
+
+ *(uint32_t *)&voodoo->vram[addr] = MIX(voodoo, dest, voodoo->banshee_blt.colorFore, pattern, src_colorkey, COLORKEY_32);
+ voodoo->changedvram[addr >> 12] = changeframecount;
+ break;
+ }
+ }
+}
+
+static void update_src_stride(voodoo_t *voodoo)
+{
+ int bpp;
+
+ switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK)
+ {
+ case SRC_FORMAT_COL_1_BPP:
+ bpp = 1;
+ break;
+ case SRC_FORMAT_COL_8_BPP:
+ bpp = 8;
+ break;
+ case SRC_FORMAT_COL_16_BPP:
+ bpp = 16;
+ break;
+ case SRC_FORMAT_COL_24_BPP:
+ bpp = 24;
+ break;
+ case SRC_FORMAT_COL_32_BPP:
+ bpp = 32;
+ break;
+
+ default:
+ bpp = 16;
+ break;
+ }
+
+ switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_PACKING_MASK)
+ {
+ case SRC_FORMAT_PACKING_STRIDE:
+ voodoo->banshee_blt.src_stride_src = voodoo->banshee_blt.src_stride; //voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK;
+ voodoo->banshee_blt.src_stride_dest = voodoo->banshee_blt.src_stride; //voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK;
+ voodoo->banshee_blt.host_data_size_src = (voodoo->banshee_blt.srcSizeX * bpp + 7) >> 3;
+ voodoo->banshee_blt.host_data_size_dest = (voodoo->banshee_blt.dstSizeX * bpp + 7) >> 3;
+// pclog("Stride packing %08x %08x bpp=%i dstSizeX=%i\n", voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest, bpp, voodoo->banshee_blt.dstSizeX);
+ break;
+
+ case SRC_FORMAT_PACKING_BYTE:
+ voodoo->banshee_blt.src_stride_src = (voodoo->banshee_blt.srcSizeX * bpp + 7) >> 3;
+ voodoo->banshee_blt.src_stride_dest = (voodoo->banshee_blt.dstSizeX * bpp + 7) >> 3;
+ voodoo->banshee_blt.host_data_size_src = voodoo->banshee_blt.src_stride_src;
+ voodoo->banshee_blt.host_data_size_dest = voodoo->banshee_blt.src_stride_dest;
+// pclog("Byte packing %08x %08x\n", voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest);
+ break;
+
+ case SRC_FORMAT_PACKING_WORD:
+ voodoo->banshee_blt.src_stride_src = ((voodoo->banshee_blt.srcSizeX * bpp + 15) >> 4) * 2;
+ voodoo->banshee_blt.src_stride_dest = ((voodoo->banshee_blt.dstSizeX * bpp + 15) >> 4) * 2;
+ voodoo->banshee_blt.host_data_size_src = voodoo->banshee_blt.src_stride_src;
+ voodoo->banshee_blt.host_data_size_dest = voodoo->banshee_blt.src_stride_dest;
+// pclog("Word packing %08x %08x\n", voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest);
+ break;
+
+ case SRC_FORMAT_PACKING_DWORD:
+ voodoo->banshee_blt.src_stride_src = ((voodoo->banshee_blt.srcSizeX * bpp + 31) >> 5) * 4;
+ voodoo->banshee_blt.src_stride_dest = ((voodoo->banshee_blt.dstSizeX * bpp + 31) >> 5) * 4;
+ voodoo->banshee_blt.host_data_size_src = voodoo->banshee_blt.src_stride_src;
+ voodoo->banshee_blt.host_data_size_dest = voodoo->banshee_blt.src_stride_dest;
+// pclog("Dword packing %08x %08x\n", voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest);
+ break;
+ }
+}
+
+static void end_command(voodoo_t *voodoo)
+{
+ /*Update dest coordinates if required*/
+ if (voodoo->banshee_blt.command & COMMAND_INC_X_START)
+ {
+ voodoo->banshee_blt.dstXY &= ~0x0000ffff;
+ voodoo->banshee_blt.dstXY |= (voodoo->banshee_blt.dstX & 0xffff);
+ }
+
+ if (voodoo->banshee_blt.command & COMMAND_INC_Y_START)
+ {
+ voodoo->banshee_blt.dstXY &= ~0xffff0000;
+ voodoo->banshee_blt.dstXY |= (voodoo->banshee_blt.dstY << 16);
+ }
+}
+
+static void banshee_do_rectfill(voodoo_t *voodoo)
+{
+ clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0];
+ int dst_y = voodoo->banshee_blt.dstY;
+ uint8_t *pattern_mono = (uint8_t *)voodoo->banshee_blt.colorPattern;
+ int pat_y = (voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0) ? 0 : (voodoo->banshee_blt.patoff_y + voodoo->banshee_blt.dstY);
+ int use_pattern_trans = (voodoo->banshee_blt.command & (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO)) ==
+ (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO);
+ uint8_t rop = voodoo->banshee_blt.command >> 24;
+
+// pclog("banshee_do_rectfill: size=%i,%i dst=%i,%i\n", voodoo->banshee_blt.dstSizeX, voodoo->banshee_blt.dstSizeY, voodoo->banshee_blt.dstX, voodoo->banshee_blt.dstY);
+// pclog("clipping: %i,%i -> %i,%i\n", clip->x_min, clip->y_min, clip->x_max, clip->y_max);
+// pclog("colorFore=%08x\n", voodoo->banshee_blt.colorFore);
+ for (voodoo->banshee_blt.cur_y = 0; voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY; voodoo->banshee_blt.cur_y++)
+ {
+ int dst_x = voodoo->banshee_blt.dstX;
+
+ if (dst_y >= clip->y_min && dst_y < clip->y_max)
+ {
+ int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX;
+ uint8_t pattern_mask = pattern_mono[pat_y & 7];
+
+ for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++)
+ {
+ int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7-(pat_x & 7)))) : 1;
+
+ if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans)
+ PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, rop, voodoo->banshee_blt.colorFore, COLORKEY_32);
+
+ dst_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1;
+ pat_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1;
+ }
+ }
+ dst_y += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1;
+ if (!(voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0))
+ pat_y += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1;
+ }
+
+ end_command(voodoo);
+}
+
+static void do_screen_to_screen_line(voodoo_t *voodoo, uint8_t *src_p, int use_x_dir, int src_x, int src_tiled)
+{
+ clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0];
+ int dst_y = voodoo->banshee_blt.dstY;
+ int pat_y = (voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0) ? 0 : (voodoo->banshee_blt.patoff_y + voodoo->banshee_blt.dstY);
+ uint8_t *pattern_mono = (uint8_t *)voodoo->banshee_blt.colorPattern;
+ int use_pattern_trans = (voodoo->banshee_blt.command & (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO)) ==
+ (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO);
+ uint8_t rop = voodoo->banshee_blt.command >> 24;
+ int src_colorkey;
+
+ switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK)
+ {
+ case SRC_FORMAT_COL_8_BPP:
+ src_colorkey = COLORKEY_8;
+ break;
+ case SRC_FORMAT_COL_16_BPP:
+ src_colorkey = COLORKEY_16;
+ break;
+ default:
+ src_colorkey = COLORKEY_32;
+ break;
+ }
+// pclog("do_screen_to_screen_line: srcFormat=%08x dst=%08x\n", voodoo->banshee_blt.srcFormat, voodoo->banshee_blt.dstFormat);
+ if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) ==
+ (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK))
+ {
+ /*No conversion required*/
+ if (dst_y >= clip->y_min && dst_y < clip->y_max)
+ {
+ int dst_x = voodoo->banshee_blt.dstX;
+ int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX;
+ uint8_t pattern_mask = pattern_mono[pat_y & 7];
+
+ for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++)
+ {
+ int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7-(pat_x & 7)))) : 1;
+ int src_x_real = (src_x * voodoo->banshee_blt.src_bpp) >> 3;
+
+ if (src_tiled)
+ src_x_real = (src_x_real & 127) + ((src_x_real >> 7) * 128*32);
+
+ if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans)
+ {
+ switch (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK)
+ {
+ case DST_FORMAT_COL_8_BPP:
+ {
+ uint32_t dst_addr = get_addr(voodoo, dst_x, dst_y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + dst_x + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t src = src_p[src_x_real];
+ uint32_t dest = voodoo->vram[dst_addr];
+ uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ?
+ ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) :
+ voodoo->banshee_blt.colorPattern8[(pat_x & 7) + (pat_y & 7)*8];
+
+ voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_8, COLORKEY_8);
+ voodoo->changedvram[dst_addr >> 12] = changeframecount;
+ break;
+ }
+ case DST_FORMAT_COL_16_BPP:
+ {
+ uint32_t dst_addr = get_addr(voodoo, dst_x*2, dst_y, 0, 0);//dst_addr = (voodoo->banshee_blt.dstBaseAddr + dst_x*2 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t src = *(uint16_t *)&src_p[src_x_real];
+ uint32_t dest = *(uint16_t *)&voodoo->vram[dst_addr];
+ uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ?
+ ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) :
+ voodoo->banshee_blt.colorPattern16[(pat_x & 7) + (pat_y & 7)*8];
+
+ *(uint16_t *)&voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_16, COLORKEY_16);
+ voodoo->changedvram[dst_addr >> 12] = changeframecount;
+ break;
+ }
+ case DST_FORMAT_COL_24_BPP:
+ {
+ uint32_t dst_addr = get_addr(voodoo, dst_x*3, dst_y, 0, 0);//dst_addr = (voodoo->banshee_blt.dstBaseAddr + dst_x*3 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t src = *(uint32_t *)&src_p[src_x_real];
+ uint32_t dest = *(uint32_t *)&voodoo->vram[dst_addr];
+ uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ?
+ ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) :
+ voodoo->banshee_blt.colorPattern24[(pat_x & 7) + (pat_y & 7)*8];
+
+ *(uint32_t *)&voodoo->vram[dst_addr] = (MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32) & 0xffffff) | (dest & 0xff000000);
+ voodoo->changedvram[dst_addr >> 12] = changeframecount;
+ break;
+ }
+ case DST_FORMAT_COL_32_BPP:
+ {
+ uint32_t dst_addr = get_addr(voodoo, dst_x*4, dst_y, 0, 0);//dst_addr = (voodoo->banshee_blt.dstBaseAddr + dst_x*4 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t src = *(uint32_t *)&src_p[src_x_real];
+ uint32_t dest = *(uint32_t *)&voodoo->vram[dst_addr];
+ uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ?
+ ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) :
+ voodoo->banshee_blt.colorPattern[(pat_x & 7) + (pat_y & 7)*8];
+
+ *(uint32_t *)&voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32);
+ voodoo->changedvram[dst_addr >> 12] = changeframecount;
+ break;
+ }
+ }
+ }
+ if (use_x_dir)
+ {
+ src_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1;
+ dst_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1;
+ pat_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1;
+ }
+ else
+ {
+ src_x++;
+ dst_x++;
+ pat_x++;
+ }
+ }
+ }
+ voodoo->banshee_blt.srcY += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1;
+ voodoo->banshee_blt.dstY += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1;
+ }
+ else
+ {
+ /*Conversion required*/
+ if (dst_y >= clip->y_min && dst_y < clip->y_max)
+ {
+// int src_x = voodoo->banshee_blt.srcX;
+ int dst_x = voodoo->banshee_blt.dstX;
+ int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX;
+ uint8_t pattern_mask = pattern_mono[pat_y & 7];
+
+ for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++)
+ {
+ int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7-(pat_x & 7)))) : 1;
+ int src_x_real = (src_x * voodoo->banshee_blt.src_bpp) >> 3;
+
+ if (src_tiled)
+ src_x_real = (src_x_real & 127) + ((src_x_real >> 7) * 128*32);
+
+ if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans)
+ {
+ uint32_t src_data = 0;
+ int transparent = 0;
+
+ switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK)
+ {
+ case SRC_FORMAT_COL_1_BPP:
+ {
+ uint8_t src_byte = src_p[src_x_real];
+ src_data = (src_byte & (0x80 >> (src_x & 7))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack;
+ if (voodoo->banshee_blt.command & COMMAND_TRANS_MONO)
+ transparent = !(src_byte & (0x80 >> (src_x & 7)));
+// pclog(" 1bpp src_byte=%02x src_x=%i src_data=%x transparent=%i\n", src_byte, src_x, src_data, transparent);
+ break;
+ }
+ case SRC_FORMAT_COL_8_BPP:
+ {
+ src_data = src_p[src_x_real];
+ break;
+ }
+ case SRC_FORMAT_COL_16_BPP:
+ {
+ uint16_t src_16 = *(uint16_t *)&src_p[src_x_real];
+ int r = (src_16 >> 11);
+ int g = (src_16 >> 5) & 0x3f;
+ int b = src_16 & 0x1f;
+
+ r = (r << 3) | (r >> 2);
+ g = (g << 2) | (g >> 4);
+ b = (b << 3) | (b >> 2);
+ src_data = (r << 16) | (g << 8) | b;
+ break;
+ }
+ case SRC_FORMAT_COL_24_BPP:
+ {
+ src_data = *(uint32_t *)&src_p[src_x_real];
+ break;
+ }
+ case SRC_FORMAT_COL_32_BPP:
+ {
+ src_data = *(uint32_t *)&src_p[src_x_real];
+ break;
+ }
+#ifndef RELEASE_BUILD
+ default:
+ fatal("banshee_do_screen_to_screen_blt: unknown srcFormat %08x\n", voodoo->banshee_blt.srcFormat);
+#endif
+ }
+
+ if ((voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) == DST_FORMAT_COL_16_BPP &&
+ (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) != SRC_FORMAT_COL_1_BPP)
+ {
+ int r = src_data >> 16;
+ int g = (src_data >> 8) & 0xff;
+ int b = src_data & 0xff;
+
+ src_data = (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11);
+ }
+
+ if (!transparent)
+ PLOT(voodoo, dst_x, dst_y, pat_x, pat_y, pattern_mask, rop, src_data, src_colorkey);
+ }
+ if (use_x_dir)
+ {
+ src_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1;
+ dst_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1;
+ pat_x += (voodoo->banshee_blt.command & COMMAND_DX) ? -1 : 1;
+ }
+ else
+ {
+ src_x++;
+ dst_x++;
+ pat_x++;
+ }
+ }
+ }
+ voodoo->banshee_blt.srcY += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1;
+ voodoo->banshee_blt.dstY += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1;
+ }
+}
+
+static void banshee_do_screen_to_screen_blt(voodoo_t *voodoo)
+{
+// pclog("screen_to_screen: %08x %08x %08x\n", voodoo->banshee_blt.srcFormat, voodoo->banshee_blt.src_stride, voodoo->banshee_blt.src_stride_dest);
+// return;
+ for (voodoo->banshee_blt.cur_y = 0; voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY; voodoo->banshee_blt.cur_y++)
+ {
+ uint32_t src_addr = get_addr(voodoo, 0, voodoo->banshee_blt.srcY, 1, voodoo->banshee_blt.src_stride_dest);
+// if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP)
+// pclog(" srcY=%i src_addr=%08x\n", voodoo->banshee_blt.srcY, src_addr);
+ do_screen_to_screen_line(voodoo, &voodoo->vram[src_addr], 1, voodoo->banshee_blt.srcX, voodoo->banshee_blt.srcBaseAddr_tiled);
+ }
+ end_command(voodoo);
+}
+
+static void banshee_do_host_to_screen_blt(voodoo_t *voodoo, int count, uint32_t data)
+{
+// if (voodoo->banshee_blt.dstBaseAddr == 0xee5194)
+// pclog("banshee_do_host_to_screen_blt: data=%08x host_data_count=%i src_stride_dest=%i host_data_size_dest=%i\n", data, voodoo->banshee_blt.host_data_count, voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest);
+
+ if (voodoo->banshee_blt.srcFormat & SRC_FORMAT_BYTE_SWIZZLE)
+ data = (data >> 24) | ((data >> 8) & 0xff00) | ((data << 8) & 0xff0000) | (data << 24);
+ if (voodoo->banshee_blt.srcFormat & SRC_FORMAT_WORD_SWIZZLE)
+ data = (data >> 16) | (data << 16);
+
+ if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_PACKING_MASK) == SRC_FORMAT_PACKING_STRIDE)
+ {
+ int last_byte;
+
+ if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP)
+ last_byte = ((voodoo->banshee_blt.srcX & 31) + voodoo->banshee_blt.dstSizeX + 7) >> 3;
+ else
+ last_byte = (voodoo->banshee_blt.srcX & 3) + voodoo->banshee_blt.host_data_size_dest;
+
+ *(uint32_t *)&voodoo->banshee_blt.host_data[voodoo->banshee_blt.host_data_count] = data;
+ voodoo->banshee_blt.host_data_count += 4;
+ if (voodoo->banshee_blt.host_data_count >= last_byte)
+ {
+// pclog(" %i %i srcX=%i srcFormat=%08x\n", voodoo->banshee_blt.cur_y, voodoo->banshee_blt.dstSizeY, voodoo->banshee_blt.srcX);
+ if (voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY)
+ {
+ if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP)
+ do_screen_to_screen_line(voodoo, &voodoo->banshee_blt.host_data[(voodoo->banshee_blt.srcX >> 3) & 3], 0, voodoo->banshee_blt.srcX & 7, 0);
+ else
+ do_screen_to_screen_line(voodoo, &voodoo->banshee_blt.host_data[voodoo->banshee_blt.srcX & 3], 0, 0, 0);
+ voodoo->banshee_blt.cur_y++;
+ if (voodoo->banshee_blt.cur_y == voodoo->banshee_blt.dstSizeY)
+ end_command(voodoo);
+ }
+
+ if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP)
+ voodoo->banshee_blt.srcX += (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK) << 3;
+ else
+ voodoo->banshee_blt.srcX += (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK);
+
+ voodoo->banshee_blt.host_data_count = 0;
+ }
+ }
+ else
+ {
+ *(uint32_t *)&voodoo->banshee_blt.host_data[voodoo->banshee_blt.host_data_count] = data;
+ voodoo->banshee_blt.host_data_count += 4;
+ while (voodoo->banshee_blt.host_data_count >= voodoo->banshee_blt.src_stride_dest)
+ {
+ voodoo->banshee_blt.host_data_count -= voodoo->banshee_blt.src_stride_dest;
+
+// pclog(" %i %i\n", voodoo->banshee_blt.cur_y, voodoo->banshee_blt.dstSizeY);
+ if (voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY)
+ {
+ do_screen_to_screen_line(voodoo, voodoo->banshee_blt.host_data, 0, 0, 0);
+ voodoo->banshee_blt.cur_y++;
+ if (voodoo->banshee_blt.cur_y == voodoo->banshee_blt.dstSizeY)
+ end_command(voodoo);
+ }
+
+ if (voodoo->banshee_blt.host_data_count)
+ {
+// pclog(" remaining=%i\n", voodoo->banshee_blt.host_data_count);
+ *(uint32_t *)&voodoo->banshee_blt.host_data[0] = data >> (4-voodoo->banshee_blt.host_data_count)*8;
+ }
+ }
+ }
+}
+
+static void do_screen_to_screen_stretch_line(voodoo_t *voodoo,uint8_t *src_p, int src_x, int *src_y)
+{
+ clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0];
+// int src_y = voodoo->banshee_blt.srcY;
+ int dst_y = voodoo->banshee_blt.dstY;
+ int pat_y = (voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0) ? 0 : (voodoo->banshee_blt.patoff_y + voodoo->banshee_blt.dstY);
+ uint8_t *pattern_mono = (uint8_t *)voodoo->banshee_blt.colorPattern;
+ int use_pattern_trans = (voodoo->banshee_blt.command & (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO)) ==
+ (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO);
+ uint32_t *colorPattern = voodoo->banshee_blt.colorPattern;
+
+ //int error_y = voodoo->banshee_blt.dstSizeY / 2;
+
+/* pclog("banshee_do_screen_to_screen_stretch_blt:\n");
+ pclog(" srcXY=%i,%i srcsizeXY=%i,%i\n", voodoo->banshee_blt.srcX, voodoo->banshee_blt.srcY, voodoo->banshee_blt.srcSizeX, voodoo->banshee_blt.srcSizeY);
+ pclog(" dstXY=%i,%i dstsizeXY=%i,%i\n", voodoo->banshee_blt.dstX, voodoo->banshee_blt.dstY, voodoo->banshee_blt.dstSizeX, voodoo->banshee_blt.dstSizeY);*/
+ if (dst_y >= clip->y_min && dst_y < clip->y_max)
+ {
+// int src_x = voodoo->banshee_blt.srcX;
+ int dst_x = voodoo->banshee_blt.dstX;
+ int pat_x = voodoo->banshee_blt.patoff_x + voodoo->banshee_blt.dstX;
+ uint8_t pattern_mask = pattern_mono[pat_y & 7];
+ int error_x = voodoo->banshee_blt.dstSizeX / 2;
+
+// pclog(" Plot dest line %03i : src line %03i\n", dst_y, src_y);
+ for (voodoo->banshee_blt.cur_x = 0; voodoo->banshee_blt.cur_x < voodoo->banshee_blt.dstSizeX; voodoo->banshee_blt.cur_x++)
+ {
+ int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7-(pat_x & 7)))) : 1;
+
+ if (dst_x >= clip->x_min && dst_x < clip->x_max && pattern_trans)
+ {
+ switch (voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK)
+ {
+ case DST_FORMAT_COL_8_BPP:
+ {
+ uint32_t dst_addr = get_addr(voodoo, dst_x, dst_y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + dst_x + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t src = src_p[src_x];
+ uint32_t dest = voodoo->vram[dst_addr];
+ uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ?
+ ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) :
+ colorPattern[(pat_x & 7) + (pat_y & 7)*8];
+
+ voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_8, COLORKEY_8);
+// pclog("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, voodoo->vram[dst_addr]);
+ voodoo->changedvram[dst_addr >> 12] = changeframecount;
+ break;
+ }
+ case DST_FORMAT_COL_16_BPP:
+ {
+ uint32_t dst_addr = get_addr(voodoo, dst_x*2, dst_y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + dst_x*2 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t src = *(uint16_t *)&src_p[src_x*2];
+ uint32_t dest = *(uint16_t *)&voodoo->vram[dst_addr];
+ uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ?
+ ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) :
+ colorPattern[(pat_x & 7) + (pat_y & 7)*8];
+
+ *(uint16_t *)&voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_16, COLORKEY_16);
+// pclog("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, *(uint16_t *)&voodoo->vram[dst_addr]);
+ voodoo->changedvram[dst_addr >> 12] = changeframecount;
+ break;
+ }
+ case DST_FORMAT_COL_24_BPP:
+ {
+ uint32_t dst_addr = get_addr(voodoo, dst_x*3, dst_y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + dst_x*3 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t src = *(uint32_t *)&src_p[src_x*3];
+ uint32_t dest = *(uint32_t *)&voodoo->vram[dst_addr];
+ uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ?
+ ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) :
+ colorPattern[(pat_x & 7) + (pat_y & 7)*8];
+
+ *(uint32_t *)&voodoo->vram[dst_addr] = (MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32) & 0xffffff) | (*(uint32_t *)&voodoo->vram[dst_addr] & 0xff000000);
+// pclog("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, voodoo->vram[dst_addr]);
+ voodoo->changedvram[dst_addr >> 12] = changeframecount;
+ break;
+ }
+ case DST_FORMAT_COL_32_BPP:
+ {
+ uint32_t dst_addr = get_addr(voodoo, dst_x*4, dst_y, 0, 0);//(voodoo->banshee_blt.dstBaseAddr + dst_x*4 + dst_y*voodoo->banshee_blt.dst_stride) & voodoo->fb_mask;
+ uint32_t src = *(uint32_t *)&src_p[src_x*4];
+ uint32_t dest = *(uint32_t *)&voodoo->vram[dst_addr];
+ uint32_t pattern = (voodoo->banshee_blt.command & COMMAND_PATTERN_MONO) ?
+ ((pattern_mask & (1 << (7-(pat_x & 7)))) ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack) :
+ colorPattern[(pat_x & 7) + (pat_y & 7)*8];
+
+ *(uint32_t *)&voodoo->vram[dst_addr] = MIX(voodoo, dest, src, pattern, COLORKEY_32, COLORKEY_32);
+// pclog("%i,%i : sdp=%02x,%02x,%02x res=%02x\n", voodoo->banshee_blt.cur_x, voodoo->banshee_blt.cur_y, src, dest, pattern, voodoo->vram[dst_addr]);
+ voodoo->changedvram[dst_addr >> 12] = changeframecount;
+ break;
+ }
+ }
+ }
+
+ error_x -= voodoo->banshee_blt.srcSizeX;
+ while (error_x < 0)
+ {
+ error_x += voodoo->banshee_blt.dstSizeX;
+ src_x++;
+ }
+ dst_x++;
+ pat_x++;
+ }
+ }
+
+ voodoo->banshee_blt.bres_error_0 -= voodoo->banshee_blt.srcSizeY;
+ while (voodoo->banshee_blt.bres_error_0 < 0)
+ {
+ voodoo->banshee_blt.bres_error_0 += voodoo->banshee_blt.dstSizeY;
+ if (src_y)
+ (*src_y) += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1;
+ }
+ voodoo->banshee_blt.dstY += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1;
+// pat_y += (voodoo->banshee_blt.command & COMMAND_DY) ? -1 : 1;
+}
+
+static void banshee_do_screen_to_screen_stretch_blt(voodoo_t *voodoo)
+{
+// pclog("screen_to_screen: %08x %08x %08x\n", voodoo->banshee_blt.srcFormat, voodoo->banshee_blt.src_stride, voodoo->banshee_blt.src_stride_dest);
+// return;
+ for (voodoo->banshee_blt.cur_y = 0; voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY; voodoo->banshee_blt.cur_y++)
+ {
+ uint32_t src_addr = get_addr(voodoo, 0, voodoo->banshee_blt.srcY, 1, voodoo->banshee_blt.src_stride_src);//(voodoo->banshee_blt.srcBaseAddr + voodoo->banshee_blt.srcY*voodoo->banshee_blt.src_stride_src) & voodoo->fb_mask;
+// pclog("scale_blit %i %08x %08x\n", voodoo->banshee_blt.cur_y, src_addr, voodoo->banshee_blt.command);
+// if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP)
+// pclog(" srcY=%i src_addr=%08x\n", voodoo->banshee_blt.srcY, src_addr);
+ do_screen_to_screen_stretch_line(voodoo, &voodoo->vram[src_addr], voodoo->banshee_blt.srcX, &voodoo->banshee_blt.srcY);
+ }
+ end_command(voodoo);
+}
+
+static void banshee_do_host_to_screen_stretch_blt(voodoo_t *voodoo, int count, uint32_t data)
+{
+// if (voodoo->banshee_blt.dstBaseAddr == 0xee5194)
+// pclog("banshee_do_host_to_screen_blt: data=%08x host_data_count=%i src_stride_dest=%i host_data_size_dest=%i\n", data, voodoo->banshee_blt.host_data_count, voodoo->banshee_blt.src_stride_dest, voodoo->banshee_blt.host_data_size_dest);
+
+ if (voodoo->banshee_blt.srcFormat & SRC_FORMAT_BYTE_SWIZZLE)
+ data = (data >> 24) | ((data >> 8) & 0xff00) | ((data << 8) & 0xff0000) | (data << 24);
+ if (voodoo->banshee_blt.srcFormat & SRC_FORMAT_WORD_SWIZZLE)
+ data = (data >> 16) | (data << 16);
+
+ if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_PACKING_MASK) == SRC_FORMAT_PACKING_STRIDE)
+ {
+ int last_byte = (voodoo->banshee_blt.srcX & 3) + voodoo->banshee_blt.host_data_size_src;
+
+ *(uint32_t *)&voodoo->banshee_blt.host_data[voodoo->banshee_blt.host_data_count] = data;
+ voodoo->banshee_blt.host_data_count += 4;
+ if (voodoo->banshee_blt.host_data_count >= last_byte)
+ {
+// pclog(" %i %i srcX=%i srcFormat=%08x\n", voodoo->banshee_blt.cur_y, voodoo->banshee_blt.dstSizeY, voodoo->banshee_blt.srcX);
+ if (voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY)
+ {
+ if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP)
+ do_screen_to_screen_stretch_line(voodoo, &voodoo->banshee_blt.host_data[(voodoo->banshee_blt.srcX >> 3) & 3], voodoo->banshee_blt.srcX & 7, NULL);
+ else
+ do_screen_to_screen_stretch_line(voodoo, &voodoo->banshee_blt.host_data[voodoo->banshee_blt.srcX & 3], 0, NULL);
+ voodoo->banshee_blt.cur_y++;
+ if (voodoo->banshee_blt.cur_y == voodoo->banshee_blt.dstSizeY)
+ end_command(voodoo);
+ }
+
+ if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_1_BPP)
+ voodoo->banshee_blt.srcX += (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK) << 3;
+ else
+ voodoo->banshee_blt.srcX += (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK);
+
+ voodoo->banshee_blt.host_data_count = 0;
+ }
+ }
+ else
+ {
+ *(uint32_t *)&voodoo->banshee_blt.host_data[voodoo->banshee_blt.host_data_count] = data;
+ voodoo->banshee_blt.host_data_count += 4;
+ while (voodoo->banshee_blt.host_data_count >= voodoo->banshee_blt.src_stride_src)
+ {
+ voodoo->banshee_blt.host_data_count -= voodoo->banshee_blt.src_stride_src;
+
+// pclog(" %i %i\n", voodoo->banshee_blt.cur_y, voodoo->banshee_blt.dstSizeY);
+ if (voodoo->banshee_blt.cur_y < voodoo->banshee_blt.dstSizeY)
+ {
+ do_screen_to_screen_stretch_line(voodoo, voodoo->banshee_blt.host_data, 0, NULL);
+ voodoo->banshee_blt.cur_y++;
+ if (voodoo->banshee_blt.cur_y == voodoo->banshee_blt.dstSizeY)
+ end_command(voodoo);
+ }
+
+ if (voodoo->banshee_blt.host_data_count)
+ {
+// pclog(" remaining=%i\n", voodoo->banshee_blt.host_data_count);
+ *(uint32_t *)&voodoo->banshee_blt.host_data[0] = data >> (4-voodoo->banshee_blt.host_data_count)*8;
+ }
+ }
+ }
+}
+
+static void step_line(voodoo_t *voodoo)
+{
+ if (voodoo->banshee_blt.line_pix_pos == voodoo->banshee_blt.line_rep_cnt)
+ {
+ voodoo->banshee_blt.line_pix_pos = 0;
+ if (voodoo->banshee_blt.line_bit_pos == voodoo->banshee_blt.line_bit_mask_size)
+ voodoo->banshee_blt.line_bit_pos = 0;
+ else
+ voodoo->banshee_blt.line_bit_pos++;
+ }
+ else
+ voodoo->banshee_blt.line_pix_pos++;
+}
+
+static void banshee_do_line(voodoo_t *voodoo, int draw_last_pixel)
+{
+ clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0];
+ uint8_t rop = voodoo->banshee_blt.command >> 24;
+ int dx = ABS(voodoo->banshee_blt.dstX - voodoo->banshee_blt.srcX);
+ int dy = ABS(voodoo->banshee_blt.dstY - voodoo->banshee_blt.srcY);
+ int x_inc = (voodoo->banshee_blt.dstX > voodoo->banshee_blt.srcX) ? 1 : -1;
+ int y_inc = (voodoo->banshee_blt.dstY > voodoo->banshee_blt.srcY) ? 1 : -1;
+ int x = voodoo->banshee_blt.srcX;
+ int y = voodoo->banshee_blt.srcY;
+ int error;
+ uint32_t stipple = (voodoo->banshee_blt.command & COMMAND_STIPPLE_LINE) ?
+ voodoo->banshee_blt.lineStipple : ~0;
+
+ if (dx > dy) /*X major*/
+ {
+ error = dx/2;
+ while (x != voodoo->banshee_blt.dstX)
+ {
+ int mask = stipple & (1 << voodoo->banshee_blt.line_bit_pos);
+ int pattern_trans = (voodoo->banshee_blt.command & COMMAND_TRANS_MONO) ? mask : 1;
+
+ if (y >= clip->y_min && y < clip->y_max && x >= clip->x_min && x < clip->x_max && pattern_trans)
+ PLOT_LINE(voodoo, x, y, rop, mask ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack, COLORKEY_32);
+
+ error -= dy;
+ if (error < 0)
+ {
+ error += dx;
+ y += y_inc;
+ }
+ x += x_inc;
+ step_line(voodoo);
+ }
+ }
+ else /*Y major*/
+ {
+ error = dy/2;
+ while (y != voodoo->banshee_blt.dstY)
+ {
+ int mask = stipple & (1 << voodoo->banshee_blt.line_bit_pos);
+ int pattern_trans = (voodoo->banshee_blt.command & COMMAND_TRANS_MONO) ? mask : 1;
+
+ if (y >= clip->y_min && y < clip->y_max && x >= clip->x_min && x < clip->x_max && pattern_trans)
+ PLOT_LINE(voodoo, x, y, rop, mask ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack, COLORKEY_32);
+
+ error -= dx;
+ if (error < 0)
+ {
+ error += dy;
+ x += x_inc;
+ }
+ y += y_inc;
+ step_line(voodoo);
+ }
+ }
+
+ if (draw_last_pixel)
+ {
+ int mask = stipple & (1 << voodoo->banshee_blt.line_bit_pos);
+ int pattern_trans = (voodoo->banshee_blt.command & COMMAND_TRANS_MONO) ? mask : 1;
+
+ if (y >= clip->y_min && y < clip->y_max && x >= clip->x_min && x < clip->x_max && pattern_trans)
+ PLOT_LINE(voodoo, x, y, rop, mask ? voodoo->banshee_blt.colorFore : voodoo->banshee_blt.colorBack, COLORKEY_32);
+ }
+
+ voodoo->banshee_blt.srcXY = (x & 0xffff) | (y << 16);
+ voodoo->banshee_blt.srcX = x;
+ voodoo->banshee_blt.srcY = y;
+}
+
+static void banshee_polyfill_start(voodoo_t *voodoo)
+{
+ voodoo->banshee_blt.lx[0] = voodoo->banshee_blt.srcX;
+ voodoo->banshee_blt.ly[0] = voodoo->banshee_blt.srcY;
+ voodoo->banshee_blt.rx[0] = voodoo->banshee_blt.dstX;
+ voodoo->banshee_blt.ry[0] = voodoo->banshee_blt.dstY;
+ voodoo->banshee_blt.lx[1] = voodoo->banshee_blt.srcX;
+ voodoo->banshee_blt.ly[1] = voodoo->banshee_blt.srcY;
+ voodoo->banshee_blt.rx[1] = voodoo->banshee_blt.dstX;
+ voodoo->banshee_blt.ry[1] = voodoo->banshee_blt.dstY;
+ voodoo->banshee_blt.lx_cur = voodoo->banshee_blt.srcX;
+ voodoo->banshee_blt.rx_cur = voodoo->banshee_blt.dstX;
+}
+
+static void banshee_polyfill_continue(voodoo_t *voodoo, uint32_t data)
+{
+ clip_t *clip = &voodoo->banshee_blt.clip[(voodoo->banshee_blt.command & COMMAND_CLIP_SEL) ? 1 : 0];
+ uint8_t *pattern_mono = (uint8_t *)voodoo->banshee_blt.colorPattern;
+ int use_pattern_trans = (voodoo->banshee_blt.command & (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO)) ==
+ (COMMAND_PATTERN_MONO | COMMAND_TRANS_MONO);
+ uint8_t rop = voodoo->banshee_blt.command >> 24;
+ int y = MAX(voodoo->banshee_blt.ly[0], voodoo->banshee_blt.ry[0]);
+ int y_end;
+
+// pclog("Polyfill : data %08x\n", data);
+
+ /*if r1.y>=l1.y, next vertex is left*/
+ if (voodoo->banshee_blt.ry[1] >= voodoo->banshee_blt.ly[1])
+ {
+ voodoo->banshee_blt.lx[1] = ((int32_t)(data << 19)) >> 19;
+ voodoo->banshee_blt.ly[1] = ((int32_t)(data << 3)) >> 19;
+ voodoo->banshee_blt.dx[0] = ABS(voodoo->banshee_blt.lx[1] - voodoo->banshee_blt.lx[0]);
+ voodoo->banshee_blt.dy[0] = ABS(voodoo->banshee_blt.ly[1] - voodoo->banshee_blt.ly[0]);
+ voodoo->banshee_blt.x_inc[0] = (voodoo->banshee_blt.lx[1] > voodoo->banshee_blt.lx[0]) ? 1 : -1;
+ voodoo->banshee_blt.error[0] = voodoo->banshee_blt.dy[0] / 2;
+ }
+ else
+ {
+ voodoo->banshee_blt.rx[1] = ((int32_t)(data << 19)) >> 19;
+ voodoo->banshee_blt.ry[1] = ((int32_t)(data << 3)) >> 19;
+ voodoo->banshee_blt.dx[1] = ABS(voodoo->banshee_blt.rx[1] - voodoo->banshee_blt.rx[0]);
+ voodoo->banshee_blt.dy[1] = ABS(voodoo->banshee_blt.ry[1] - voodoo->banshee_blt.ry[0]);
+ voodoo->banshee_blt.x_inc[1] = (voodoo->banshee_blt.rx[1] > voodoo->banshee_blt.rx[0]) ? 1 : -1;
+ voodoo->banshee_blt.error[1] = voodoo->banshee_blt.dy[1] / 2;
+ }
+
+/* pclog(" verts now : %03i,%03i %03i,%03i\n", voodoo->banshee_blt.lx[0], voodoo->banshee_blt.ly[0], voodoo->banshee_blt.rx[0], voodoo->banshee_blt.ry[0]);
+ pclog(" %03i,%03i %03i,%03i\n", voodoo->banshee_blt.lx[1], voodoo->banshee_blt.ly[1], voodoo->banshee_blt.rx[1], voodoo->banshee_blt.ry[1]);
+ pclog(" left dx=%i dy=%i x_inc=%i error=%i\n", voodoo->banshee_blt.dx[0],voodoo->banshee_blt.dy[0],voodoo->banshee_blt.x_inc[0],voodoo->banshee_blt.error[0]);
+ pclog(" right dx=%i dy=%i x_inc=%i error=%i\n", voodoo->banshee_blt.dx[1],voodoo->banshee_blt.dy[1],voodoo->banshee_blt.x_inc[1],voodoo->banshee_blt.error[1]);*/
+ y_end = MIN(voodoo->banshee_blt.ly[1], voodoo->banshee_blt.ry[1]);
+// pclog("Polyfill : draw spans from %i-%i\n", y, y_end);
+ for (; y < y_end; y++)
+ {
+// pclog(" %i: %i %i\n", y, voodoo->banshee_blt.lx_cur, voodoo->banshee_blt.rx_cur);
+ /*Draw span from lx_cur to rx_cur*/
+ if (y >= clip->y_min && y < clip->y_max)
+ {
+ int pat_y = (voodoo->banshee_blt.commandExtra & CMDEXTRA_FORCE_PAT_ROW0) ? 0 : (voodoo->banshee_blt.patoff_y + y);
+ uint8_t pattern_mask = pattern_mono[pat_y & 7];
+ int x;
+
+ for (x = voodoo->banshee_blt.lx_cur; x < voodoo->banshee_blt.rx_cur; x++)
+ {
+ int pat_x = voodoo->banshee_blt.patoff_x + x;
+ int pattern_trans = use_pattern_trans ? (pattern_mask & (1 << (7-(pat_x & 7)))) : 1;
+
+ if (x >= clip->x_min && x < clip->x_max && pattern_trans)
+ PLOT(voodoo, x, y, pat_x, pat_y, pattern_mask, rop, voodoo->banshee_blt.colorFore, COLORKEY_32);
+ }
+ }
+
+ voodoo->banshee_blt.error[0] -= voodoo->banshee_blt.dx[0];
+ while (voodoo->banshee_blt.error[0] < 0)
+ {
+ voodoo->banshee_blt.error[0] += voodoo->banshee_blt.dy[0];
+ voodoo->banshee_blt.lx_cur += voodoo->banshee_blt.x_inc[0];
+ }
+ voodoo->banshee_blt.error[1] -= voodoo->banshee_blt.dx[1];
+ while (voodoo->banshee_blt.error[1] < 0)
+ {
+ voodoo->banshee_blt.error[1] += voodoo->banshee_blt.dy[1];
+ voodoo->banshee_blt.rx_cur += voodoo->banshee_blt.x_inc[1];
+ }
+ }
+
+ if (voodoo->banshee_blt.ry[1] == voodoo->banshee_blt.ly[1])
+ {
+ voodoo->banshee_blt.lx[0] = voodoo->banshee_blt.lx[1];
+ voodoo->banshee_blt.ly[0] = voodoo->banshee_blt.ly[1];
+ voodoo->banshee_blt.rx[0] = voodoo->banshee_blt.rx[1];
+ voodoo->banshee_blt.ry[0] = voodoo->banshee_blt.ry[1];
+ }
+ else if (voodoo->banshee_blt.ry[1] >= voodoo->banshee_blt.ly[1])
+ {
+ voodoo->banshee_blt.lx[0] = voodoo->banshee_blt.lx[1];
+ voodoo->banshee_blt.ly[0] = voodoo->banshee_blt.ly[1];
+ }
+ else
+ {
+ voodoo->banshee_blt.rx[0] = voodoo->banshee_blt.rx[1];
+ voodoo->banshee_blt.ry[0] = voodoo->banshee_blt.ry[1];
+ }
+}
+
+static void banshee_do_2d_blit(voodoo_t *voodoo, int count, uint32_t data)
+{
+ switch (voodoo->banshee_blt.command & COMMAND_CMD_MASK)
+ {
+ case COMMAND_CMD_NOP:
+ break;
+
+ case COMMAND_CMD_SCREEN_TO_SCREEN_BLT:
+ banshee_do_screen_to_screen_blt(voodoo);
+ break;
+
+ case COMMAND_CMD_SCREEN_TO_SCREEN_STRETCH_BLT:
+ banshee_do_screen_to_screen_stretch_blt(voodoo);
+ break;
+
+ case COMMAND_CMD_HOST_TO_SCREEN_BLT:
+ banshee_do_host_to_screen_blt(voodoo, count, data);
+ break;
+
+ case COMMAND_CMD_HOST_TO_SCREEN_STRETCH_BLT:
+ banshee_do_host_to_screen_stretch_blt(voodoo, count, data);
+ break;
+
+ case COMMAND_CMD_RECTFILL:
+ banshee_do_rectfill(voodoo);
+ break;
+
+ case COMMAND_CMD_LINE:
+ banshee_do_line(voodoo, 1);
+ break;
+
+ case COMMAND_CMD_POLYLINE:
+ banshee_do_line(voodoo, 0);
+ break;
+
+#ifndef RELEASE_BUILD
+ default:
+ fatal("banshee_do_2d_blit: unknown command=%08x\n", voodoo->banshee_blt.command);
+#endif
+ }
+}
+
+void voodoo_2d_reg_writel(voodoo_t *voodoo, uint32_t addr, uint32_t val)
+{
+// /*if ((addr & 0x1fc) != 0x80) */pclog("2D reg write %03x %08x\n", addr & 0x1fc, val);
+ switch (addr & 0x1fc)
+ {
+ case 0x08:
+ voodoo->banshee_blt.clip0Min = val;
+ voodoo->banshee_blt.clip[0].x_min = val & 0xfff;
+ voodoo->banshee_blt.clip[0].y_min = (val >> 16) & 0xfff;
+ break;
+ case 0x0c:
+ voodoo->banshee_blt.clip0Max = val;
+ voodoo->banshee_blt.clip[0].x_max = val & 0xfff;
+ voodoo->banshee_blt.clip[0].y_max = (val >> 16) & 0xfff;
+ break;
+ case 0x10:
+ voodoo->banshee_blt.dstBaseAddr = val & 0xffffff;
+ voodoo->banshee_blt.dstBaseAddr_tiled = val & 0x80000000;
+ if (voodoo->banshee_blt.dstBaseAddr_tiled)
+ voodoo->banshee_blt.dst_stride = (voodoo->banshee_blt.dstFormat & DST_FORMAT_STRIDE_MASK) * 128*32;
+ else
+ voodoo->banshee_blt.dst_stride = voodoo->banshee_blt.dstFormat & DST_FORMAT_STRIDE_MASK;
+// pclog("dstBaseAddr=%08x\n", val);
+ break;
+ case 0x14:
+ voodoo->banshee_blt.dstFormat = val;
+ if (voodoo->banshee_blt.dstBaseAddr_tiled)
+ voodoo->banshee_blt.dst_stride = (voodoo->banshee_blt.dstFormat & DST_FORMAT_STRIDE_MASK) * 128*32;
+ else
+ voodoo->banshee_blt.dst_stride = voodoo->banshee_blt.dstFormat & DST_FORMAT_STRIDE_MASK;
+// pclog("dstFormat=%08x\n", val);
+ break;
+
+ case 0x18:
+ voodoo->banshee_blt.srcColorkeyMin = val & 0xffffff;
+ break;
+ case 0x1c:
+ voodoo->banshee_blt.srcColorkeyMax = val & 0xffffff;
+ break;
+ case 0x20:
+ voodoo->banshee_blt.dstColorkeyMin = val & 0xffffff;
+ break;
+ case 0x24:
+ voodoo->banshee_blt.dstColorkeyMax = val & 0xffffff;
+ break;
+
+ case 0x28:
+ voodoo->banshee_blt.bresError0 = val;
+ voodoo->banshee_blt.bres_error_0 = val & 0xffff;
+ break;
+ case 0x2c:
+ voodoo->banshee_blt.bresError1 = val;
+ voodoo->banshee_blt.bres_error_1 = val & 0xffff;
+ break;
+
+ case 0x30:
+ voodoo->banshee_blt.rop = val;
+ voodoo->banshee_blt.rops[1] = val & 0xff;
+ voodoo->banshee_blt.rops[2] = (val >> 8) & 0xff;
+ voodoo->banshee_blt.rops[3] = (val >> 16) & 0xff;
+// pclog("rop=%08x\n", val);
+ break;
+ case 0x34:
+ voodoo->banshee_blt.srcBaseAddr = val & 0xffffff;
+ voodoo->banshee_blt.srcBaseAddr_tiled = val & 0x80000000;
+ if (voodoo->banshee_blt.srcBaseAddr_tiled)
+ voodoo->banshee_blt.src_stride = (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK) * 128*32;
+ else
+ voodoo->banshee_blt.src_stride = voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK;
+ update_src_stride(voodoo);
+// pclog("srcBaseAddr=%08x\n", val);
+ break;
+ case 0x38:
+ voodoo->banshee_blt.commandExtra = val;
+// pclog("commandExtra=%08x\n", val);
+ break;
+ case 0x3c:
+ voodoo->banshee_blt.lineStipple = val;
+ break;
+ case 0x40:
+ voodoo->banshee_blt.lineStyle = val;
+ voodoo->banshee_blt.line_rep_cnt = val & 0xff;
+ voodoo->banshee_blt.line_bit_mask_size = (val >> 8) & 0x1f;
+ voodoo->banshee_blt.line_pix_pos = (val >> 16) & 0xff;
+ voodoo->banshee_blt.line_bit_pos = (val >> 24) & 0x1f;
+ break;
+ case 0x44:
+ voodoo->banshee_blt.colorPattern[0] = val;
+// pclog("colorPattern0=%08x\n", val);
+ voodoo->banshee_blt.colorPattern24[0] = val & 0xffffff;
+ voodoo->banshee_blt.colorPattern24[1] = (voodoo->banshee_blt.colorPattern24[1] & 0xffff00) | (val >> 24);
+ voodoo->banshee_blt.colorPattern16[0] = val & 0xffff;
+ voodoo->banshee_blt.colorPattern16[1] = (val >> 16) & 0xffff;
+ voodoo->banshee_blt.colorPattern8[0] = val & 0xff;
+ voodoo->banshee_blt.colorPattern8[1] = (val >> 8) & 0xff;
+ voodoo->banshee_blt.colorPattern8[2] = (val >> 16) & 0xff;
+ voodoo->banshee_blt.colorPattern8[3] = (val >> 24) & 0xff;
+ break;
+ case 0x48:
+ voodoo->banshee_blt.colorPattern[1] = val;
+// pclog("colorPattern1=%08x\n", val);
+ voodoo->banshee_blt.colorPattern24[1] = (voodoo->banshee_blt.colorPattern24[1] & 0xff) | ((val & 0xffff) << 8);
+ voodoo->banshee_blt.colorPattern24[2] = (voodoo->banshee_blt.colorPattern24[2] & 0xff0000) | (val >> 16);
+ voodoo->banshee_blt.colorPattern16[2] = val & 0xffff;
+ voodoo->banshee_blt.colorPattern16[3] = (val >> 16) & 0xffff;
+ voodoo->banshee_blt.colorPattern8[4] = val & 0xff;
+ voodoo->banshee_blt.colorPattern8[5] = (val >> 8) & 0xff;
+ voodoo->banshee_blt.colorPattern8[6] = (val >> 16) & 0xff;
+ voodoo->banshee_blt.colorPattern8[7] = (val >> 24) & 0xff;
+ break;
+ case 0x4c:
+ voodoo->banshee_blt.clip1Min = val;
+ voodoo->banshee_blt.clip[1].x_min = val & 0xfff;
+ voodoo->banshee_blt.clip[1].y_min = (val >> 16) & 0xfff;
+ break;
+ case 0x50:
+ voodoo->banshee_blt.clip1Max = val;
+ voodoo->banshee_blt.clip[1].x_max = val & 0xfff;
+ voodoo->banshee_blt.clip[1].y_max = (val >> 16) & 0xfff;
+ break;
+ case 0x54:
+ voodoo->banshee_blt.srcFormat = val;
+ if (voodoo->banshee_blt.srcBaseAddr_tiled)
+ voodoo->banshee_blt.src_stride = (voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK) * 128*32;
+ else
+ voodoo->banshee_blt.src_stride = voodoo->banshee_blt.srcFormat & SRC_FORMAT_STRIDE_MASK;
+ update_src_stride(voodoo);
+ switch (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK)
+ {
+ case SRC_FORMAT_COL_1_BPP:
+ voodoo->banshee_blt.src_bpp = 1;
+ break;
+ case SRC_FORMAT_COL_8_BPP:
+ voodoo->banshee_blt.src_bpp = 8;
+ break;
+ case SRC_FORMAT_COL_24_BPP:
+ voodoo->banshee_blt.src_bpp = 24;
+ break;
+ case SRC_FORMAT_COL_32_BPP:
+ voodoo->banshee_blt.src_bpp = 32;
+ break;
+ case SRC_FORMAT_COL_16_BPP: default:
+ voodoo->banshee_blt.src_bpp = 16;
+ break;
+ }
+// pclog("srcFormat=%08x\n", val);
+ break;
+ case 0x58:
+ voodoo->banshee_blt.srcSize = val;
+ voodoo->banshee_blt.srcSizeX = voodoo->banshee_blt.srcSize & 0x1fff;
+ voodoo->banshee_blt.srcSizeY = (voodoo->banshee_blt.srcSize >> 16) & 0x1fff;
+ update_src_stride(voodoo);
+// pclog("srcSize=%08x\n", val);
+ break;
+ case 0x5c:
+ voodoo->banshee_blt.srcXY = val;
+ voodoo->banshee_blt.srcX = ((int32_t)(val << 19)) >> 19;
+ voodoo->banshee_blt.srcY = ((int32_t)(val << 3)) >> 19;
+ update_src_stride(voodoo);
+// pclog("srcXY=%08x\n", val);
+ break;
+ case 0x60:
+ voodoo->banshee_blt.colorBack = val;
+ break;
+ case 0x64:
+ voodoo->banshee_blt.colorFore = val;
+ break;
+ case 0x68:
+ voodoo->banshee_blt.dstSize = val;
+ voodoo->banshee_blt.dstSizeX = voodoo->banshee_blt.dstSize & 0x1fff;
+ voodoo->banshee_blt.dstSizeY = (voodoo->banshee_blt.dstSize >> 16) & 0x1fff;
+ update_src_stride(voodoo);
+// pclog("dstSize=%08x\n", val);
+ break;
+ case 0x6c:
+ voodoo->banshee_blt.dstXY = val;
+ voodoo->banshee_blt.dstX = ((int32_t)(val << 19)) >> 19;
+ voodoo->banshee_blt.dstY = ((int32_t)(val << 3)) >> 19;
+// pclog("dstXY=%08x\n", val);
+ break;
+ case 0x70:
+ voodoo_wait_for_render_thread_idle(voodoo);
+ voodoo->banshee_blt.command = val;
+ voodoo->banshee_blt.rops[0] = val >> 24;
+// pclog("command=%x %08x\n", voodoo->banshee_blt.command & COMMAND_CMD_MASK, val);
+ voodoo->banshee_blt.patoff_x = (val & COMMAND_PATOFF_X_MASK) >> COMMAND_PATOFF_X_SHIFT;
+ voodoo->banshee_blt.patoff_y = (val & COMMAND_PATOFF_Y_MASK) >> COMMAND_PATOFF_Y_SHIFT;
+ voodoo->banshee_blt.cur_x = 0;
+ voodoo->banshee_blt.cur_y = 0;
+ voodoo->banshee_blt.dstX = ((int32_t)(voodoo->banshee_blt.dstXY << 19)) >> 19;
+ voodoo->banshee_blt.dstY = ((int32_t)(voodoo->banshee_blt.dstXY << 3)) >> 19;
+ voodoo->banshee_blt.srcX = ((int32_t)(voodoo->banshee_blt.srcXY << 19)) >> 19;
+ voodoo->banshee_blt.srcY = ((int32_t)(voodoo->banshee_blt.srcXY << 3)) >> 19;
+ voodoo->banshee_blt.old_srcX = voodoo->banshee_blt.srcX;
+ voodoo->banshee_blt.host_data_remainder = 0;
+ voodoo->banshee_blt.host_data_count = 0;
+ switch (voodoo->banshee_blt.command & COMMAND_CMD_MASK)
+ {
+/* case COMMAND_CMD_SCREEN_TO_SCREEN_STRETCH_BLT:
+ if (voodoo->banshee_blt.bresError0 & BRES_ERROR_USE)
+ voodoo->banshee_blt.bres_error_0 = (int32_t)(int16_t)(voodoo->banshee_blt.bresError0 & BRES_ERROR_MASK);
+ else
+ voodoo->banshee_blt.bres_error_0 = voodoo->banshee_blt.dstSizeY / 2;
+ if (voodoo->banshee_blt.bresError1 & BRES_ERROR_USE)
+ voodoo->banshee_blt.bres_error_1 = (int32_t)(int16_t)(voodoo->banshee_blt.bresError1 & BRES_ERROR_MASK);
+ else
+ voodoo->banshee_blt.bres_error_1 = voodoo->banshee_blt.dstSizeX / 2;
+
+ if (val & COMMAND_INITIATE)
+ banshee_do_2d_blit(voodoo, -1, 0);
+ break;*/
+
+ case COMMAND_CMD_POLYFILL:
+ if (val & COMMAND_INITIATE)
+ {
+ voodoo->banshee_blt.dstXY = voodoo->banshee_blt.srcXY;
+ voodoo->banshee_blt.dstX = voodoo->banshee_blt.srcX;
+ voodoo->banshee_blt.dstY = voodoo->banshee_blt.srcY;
+ }
+ banshee_polyfill_start(voodoo);
+ break;
+
+ default:
+ if (val & COMMAND_INITIATE)
+ {
+ banshee_do_2d_blit(voodoo, -1, 0);
+ // fatal("Initiate command!\n");
+ }
+ break;
+ }
+ break;
+
+ case 0x80: case 0x84: case 0x88: case 0x8c:
+ case 0x90: case 0x94: case 0x98: case 0x9c:
+ case 0xa0: case 0xa4: case 0xa8: case 0xac:
+ case 0xb0: case 0xb4: case 0xb8: case 0xbc:
+ case 0xc0: case 0xc4: case 0xc8: case 0xcc:
+ case 0xd0: case 0xd4: case 0xd8: case 0xdc:
+ case 0xe0: case 0xe4: case 0xe8: case 0xec:
+ case 0xf0: case 0xf4: case 0xf8: case 0xfc:
+// pclog("launch %08x %08x %08x %08x\n", voodoo->banshee_blt.command, voodoo->banshee_blt.commandExtra, voodoo->banshee_blt.srcColorkeyMin, voodoo->banshee_blt.srcColorkeyMax);
+ switch (voodoo->banshee_blt.command & COMMAND_CMD_MASK)
+ {
+ case COMMAND_CMD_SCREEN_TO_SCREEN_BLT:
+ voodoo->banshee_blt.srcXY = val;
+ voodoo->banshee_blt.srcX = ((int32_t)(val << 19)) >> 19;
+ voodoo->banshee_blt.srcY = ((int32_t)(val << 3)) >> 19;
+ banshee_do_screen_to_screen_blt(voodoo);
+ break;
+
+ case COMMAND_CMD_HOST_TO_SCREEN_BLT:
+ banshee_do_2d_blit(voodoo, 32, val);
+ break;
+
+ case COMMAND_CMD_HOST_TO_SCREEN_STRETCH_BLT:
+ banshee_do_2d_blit(voodoo, 32, val);
+ break;
+
+ case COMMAND_CMD_RECTFILL:
+ voodoo->banshee_blt.dstXY = val;
+ voodoo->banshee_blt.dstX = ((int32_t)(val << 19)) >> 19;
+ voodoo->banshee_blt.dstY = ((int32_t)(val << 3)) >> 19;
+ banshee_do_rectfill(voodoo);
+ break;
+
+ case COMMAND_CMD_LINE:
+ voodoo->banshee_blt.dstXY = val;
+ voodoo->banshee_blt.dstX = ((int32_t)(val << 19)) >> 19;
+ voodoo->banshee_blt.dstY = ((int32_t)(val << 3)) >> 19;
+ banshee_do_line(voodoo, 1);
+ break;
+
+ case COMMAND_CMD_POLYLINE:
+ voodoo->banshee_blt.dstXY = val;
+ voodoo->banshee_blt.dstX = ((int32_t)(val << 19)) >> 19;
+ voodoo->banshee_blt.dstY = ((int32_t)(val << 3)) >> 19;
+ banshee_do_line(voodoo, 0);
+ break;
+
+ case COMMAND_CMD_POLYFILL:
+ banshee_polyfill_continue(voodoo, val);
+ break;
+
+#ifndef RELEASE_BUILD
+ default:
+ fatal("launch area write, command=%08x\n", voodoo->banshee_blt.command);
+#endif
+ }
+ break;
+
+ case 0x100: case 0x104: case 0x108: case 0x10c:
+ case 0x110: case 0x114: case 0x118: case 0x11c:
+ case 0x120: case 0x124: case 0x128: case 0x12c:
+ case 0x130: case 0x134: case 0x138: case 0x13c:
+ case 0x140: case 0x144: case 0x148: case 0x14c:
+ case 0x150: case 0x154: case 0x158: case 0x15c:
+ case 0x160: case 0x164: case 0x168: case 0x16c:
+ case 0x170: case 0x174: case 0x178: case 0x17c:
+ case 0x180: case 0x184: case 0x188: case 0x18c:
+ case 0x190: case 0x194: case 0x198: case 0x19c:
+ case 0x1a0: case 0x1a4: case 0x1a8: case 0x1ac:
+ case 0x1b0: case 0x1b4: case 0x1b8: case 0x1bc:
+ case 0x1c0: case 0x1c4: case 0x1c8: case 0x1cc:
+ case 0x1d0: case 0x1d4: case 0x1d8: case 0x1dc:
+ case 0x1e0: case 0x1e4: case 0x1e8: case 0x1ec:
+ case 0x1f0: case 0x1f4: case 0x1f8: case 0x1fc:
+ voodoo->banshee_blt.colorPattern[(addr >> 2) & 63] = val;
+ if ((addr & 0x1fc) < 0x1c0)
+ {
+ int base_addr = (addr & 0xfc) / 0xc;
+ uintptr_t src_p = (uintptr_t)&voodoo->banshee_blt.colorPattern[base_addr * 3];
+ int col24 = base_addr * 4;
+
+ voodoo->banshee_blt.colorPattern24[col24] = *(uint32_t *)src_p & 0xffffff;
+ voodoo->banshee_blt.colorPattern24[col24 + 1] = *(uint32_t *)(src_p + 3) & 0xffffff;
+ voodoo->banshee_blt.colorPattern24[col24 + 2] = *(uint32_t *)(src_p + 6) & 0xffffff;
+ voodoo->banshee_blt.colorPattern24[col24 + 3] = *(uint32_t *)(src_p + 9) & 0xffffff;
+ }
+ if ((addr & 0x1fc) < 0x180)
+ {
+ voodoo->banshee_blt.colorPattern16[(addr >> 1) & 62] = val & 0xffff;
+ voodoo->banshee_blt.colorPattern16[((addr >> 1) & 62) + 1] = (val >> 16) & 0xffff;
+ }
+ if ((addr & 0x1fc) < 0x140)
+ {
+ voodoo->banshee_blt.colorPattern8[addr & 60] = val & 0xff;
+ voodoo->banshee_blt.colorPattern8[(addr & 60) + 1] = (val >> 8) & 0xff;
+ voodoo->banshee_blt.colorPattern8[(addr & 60) + 2] = (val >> 16) & 0xff;
+ voodoo->banshee_blt.colorPattern8[(addr & 60) + 3] = (val >> 24) & 0xff;
+ }
+// pclog("colorPattern%02x=%08x\n", (addr >> 2) & 63, val);
+ break;
+
+#ifndef RELEASE_BUILD
+ default:
+ fatal("Unknown 2D reg write %03x %08x\n", addr & 0x1fc, val);
+#endif
+ }
+}
diff --git a/src/vid_voodoo_banshee_blitter.h b/src/vid_voodoo_banshee_blitter.h
new file mode 100644
index 0000000..cc7a8f2
--- /dev/null
+++ b/src/vid_voodoo_banshee_blitter.h
@@ -0,0 +1 @@
+void voodoo_2d_reg_writel(voodoo_t *voodoo, uint32_t addr, uint32_t val);
diff --git a/src/vid_voodoo_blitter.c b/src/vid_voodoo_blitter.c
new file mode 100644
index 0000000..af7e204
--- /dev/null
+++ b/src/vid_voodoo_blitter.c
@@ -0,0 +1,509 @@
+#include
+#include
+#include "ibm.h"
+#include "device.h"
+#include "mem.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_svga.h"
+#include "vid_voodoo.h"
+#include "vid_voodoo_common.h"
+#include "vid_voodoo_blitter.h"
+#include "vid_voodoo_dither.h"
+#include "vid_voodoo_regs.h"
+#include "vid_voodoo_render.h"
+
+enum
+{
+ BLIT_COMMAND_SCREEN_TO_SCREEN = 0,
+ BLIT_COMMAND_CPU_TO_SCREEN = 1,
+ BLIT_COMMAND_RECT_FILL = 2,
+ BLIT_COMMAND_SGRAM_FILL = 3
+};
+
+enum
+{
+ BLIT_SRC_1BPP = (0 << 3),
+ BLIT_SRC_1BPP_BYTE_PACKED = (1 << 3),
+ BLIT_SRC_16BPP = (2 << 3),
+ BLIT_SRC_24BPP = (3 << 3),
+ BLIT_SRC_24BPP_DITHER_2X2 = (4 << 3),
+ BLIT_SRC_24BPP_DITHER_4X4 = (5 << 3)
+};
+
+enum
+{
+ BLIT_SRC_RGB_ARGB = (0 << 6),
+ BLIT_SRC_RGB_ABGR = (1 << 6),
+ BLIT_SRC_RGB_RGBA = (2 << 6),
+ BLIT_SRC_RGB_BGRA = (3 << 6)
+};
+
+enum
+{
+ BLIT_COMMAND_MASK = 7,
+ BLIT_SRC_FORMAT = (7 << 3),
+ BLIT_SRC_RGB_FORMAT = (3 << 6),
+ BLIT_SRC_CHROMA = (1 << 10),
+ BLIT_DST_CHROMA = (1 << 12),
+ BLIT_CLIPPING_ENABLED = (1 << 16)
+};
+
+enum
+{
+ BLIT_ROP_DST_PASS = (1 << 0),
+ BLIT_ROP_SRC_PASS = (1 << 1)
+};
+
+#define MIX(src_dat, dst_dat, rop) \
+ switch (rop) \
+ { \
+ case 0x0: dst_dat = 0; break; \
+ case 0x1: dst_dat = ~(src_dat | dst_dat); break; \
+ case 0x2: dst_dat = ~src_dat & dst_dat; break; \
+ case 0x3: dst_dat = ~src_dat; break; \
+ case 0x4: dst_dat = src_dat & ~dst_dat; break; \
+ case 0x5: dst_dat = ~dst_dat; break; \
+ case 0x6: dst_dat = src_dat ^ dst_dat; break; \
+ case 0x7: dst_dat = ~(src_dat & dst_dat); break; \
+ case 0x8: dst_dat = src_dat & dst_dat; break; \
+ case 0x9: dst_dat = ~(src_dat ^ dst_dat); break; \
+ case 0xa: dst_dat = dst_dat; break; \
+ case 0xb: dst_dat = ~src_dat | dst_dat; break; \
+ case 0xc: dst_dat = src_dat; break; \
+ case 0xd: dst_dat = src_dat | ~dst_dat; break; \
+ case 0xe: dst_dat = src_dat | dst_dat; break; \
+ case 0xf: dst_dat = 0xffff; break; \
+ }
+
+void voodoo_v2_blit_start(voodoo_t *voodoo)
+{
+ uint64_t dat64;
+ int size_x = ABS(voodoo->bltSizeX), size_y = ABS(voodoo->bltSizeY);
+ int x_dir = (voodoo->bltSizeX > 0) ? 1 : -1;
+ int y_dir = (voodoo->bltSizeY > 0) ? 1 : -1;
+ int dst_x;
+ int src_y = voodoo->bltSrcY & 0x7ff, dst_y = voodoo->bltDstY & 0x7ff;
+ int src_stride = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcXYStride & 0x3f) * 32*2) : (voodoo->bltSrcXYStride & 0xff8);
+ int dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32*2) : (voodoo->bltDstXYStride & 0xff8);
+ uint32_t src_base_addr = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcBaseAddr & 0x3ff) << 12) : (voodoo->bltSrcBaseAddr & 0x3ffff8);
+ uint32_t dst_base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8);
+ int x, y;
+
+/* pclog("blit_start: command=%08x srcX=%i srcY=%i dstX=%i dstY=%i sizeX=%i sizeY=%i color=%04x,%04x\n",
+ voodoo->bltCommand, voodoo->bltSrcX, voodoo->bltSrcY, voodoo->bltDstX, voodoo->bltDstY, voodoo->bltSizeX, voodoo->bltSizeY, voodoo->bltColorFg, voodoo->bltColorBg);*/
+
+ voodoo_wait_for_render_thread_idle(voodoo);
+
+ switch (voodoo->bltCommand & BLIT_COMMAND_MASK)
+ {
+ case BLIT_COMMAND_SCREEN_TO_SCREEN:
+ for (y = 0; y <= size_y; y++)
+ {
+ uint16_t *src = (uint16_t *)&voodoo->fb_mem[src_base_addr + src_y*src_stride];
+ uint16_t *dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + dst_y*dst_stride];
+ int src_x = voodoo->bltSrcX, dst_x = voodoo->bltDstX;
+
+ for (x = 0; x <= size_x; x++)
+ {
+ uint16_t src_dat = src[src_x];
+ uint16_t dst_dat = dst[dst_x];
+ int rop = 0;
+
+ if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED)
+ {
+ if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight ||
+ dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY)
+ goto skip_pixel_blit;
+ }
+
+ if (voodoo->bltCommand & BLIT_SRC_CHROMA)
+ {
+ int r = (src_dat >> 11);
+ int g = (src_dat >> 5) & 0x3f;
+ int b = src_dat & 0x1f;
+
+ if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR &&
+ g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG &&
+ b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB)
+ rop |= BLIT_ROP_SRC_PASS;
+ }
+ if (voodoo->bltCommand & BLIT_DST_CHROMA)
+ {
+ int r = (dst_dat >> 11);
+ int g = (dst_dat >> 5) & 0x3f;
+ int b = dst_dat & 0x1f;
+
+ if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR &&
+ g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG &&
+ b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB)
+ rop |= BLIT_ROP_DST_PASS;
+ }
+
+ MIX(src_dat, dst_dat, voodoo->bltRop[rop]);
+
+ dst[dst_x] = dst_dat;
+skip_pixel_blit:
+ src_x += x_dir;
+ dst_x += x_dir;
+ }
+
+ src_y += y_dir;
+ dst_y += y_dir;
+ }
+ break;
+
+ case BLIT_COMMAND_CPU_TO_SCREEN:
+ voodoo->blt.dst_x = voodoo->bltDstX;
+ voodoo->blt.dst_y = voodoo->bltDstY;
+ voodoo->blt.cur_x = 0;
+ voodoo->blt.size_x = size_x;
+ voodoo->blt.size_y = size_y;
+ voodoo->blt.x_dir = x_dir;
+ voodoo->blt.y_dir = y_dir;
+ voodoo->blt.dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32*2) : (voodoo->bltDstXYStride & 0xff8);
+ break;
+
+ case BLIT_COMMAND_RECT_FILL:
+ for (y = 0; y <= size_y; y++)
+ {
+ uint16_t *dst;
+ int dst_x = voodoo->bltDstX;
+
+ if (SLI_ENABLED)
+ {
+ if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) ||
+ ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1)))
+ goto skip_line_fill;
+ dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + (dst_y >> 1) * dst_stride];
+ }
+ else
+ dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + dst_y*dst_stride];
+
+ for (x = 0; x <= size_x; x++)
+ {
+ if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED)
+ {
+ if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight ||
+ dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY)
+ goto skip_pixel_fill;
+ }
+
+ dst[dst_x] = voodoo->bltColorFg;
+skip_pixel_fill:
+ dst_x += x_dir;
+ }
+skip_line_fill:
+ dst_y += y_dir;
+ }
+ break;
+
+ case BLIT_COMMAND_SGRAM_FILL:
+ /*32x32 tiles - 2kb*/
+ dst_y = voodoo->bltDstY & 0x3ff;
+ size_x = voodoo->bltSizeX & 0x1ff; //512*8 = 4kb
+ size_y = voodoo->bltSizeY & 0x3ff;
+
+ dat64 = voodoo->bltColorFg | ((uint64_t)voodoo->bltColorFg << 16) |
+ ((uint64_t)voodoo->bltColorFg << 32) | ((uint64_t)voodoo->bltColorFg << 48);
+
+ for (y = 0; y <= size_y; y++)
+ {
+ uint64_t *dst;
+
+ /*This may be wrong*/
+ if (!y)
+ {
+ dst_x = voodoo->bltDstX & 0x1ff;
+ size_x = 511 - dst_x;
+ }
+ else if (y < size_y)
+ {
+ dst_x = 0;
+ size_x = 511;
+ }
+ else
+ {
+ dst_x = 0;
+ size_x = voodoo->bltSizeX & 0x1ff;
+ }
+
+ dst = (uint64_t *)&voodoo->fb_mem[(dst_y*512*8 + dst_x*8) & voodoo->fb_mask];
+
+ for (x = 0; x <= size_x; x++)
+ dst[x] = dat64;
+
+ dst_y++;
+ }
+ break;
+
+ default:
+ fatal("bad blit command %08x\n", voodoo->bltCommand);
+ }
+}
+
+void voodoo_v2_blit_data(voodoo_t *voodoo, uint32_t data)
+{
+ int src_bits = 32;
+ uint32_t base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8);
+ uint32_t addr;
+ uint16_t *dst;
+
+ if ((voodoo->bltCommand & BLIT_COMMAND_MASK) != BLIT_COMMAND_CPU_TO_SCREEN)
+ return;
+
+ if (SLI_ENABLED)
+ {
+ addr = base_addr + (voodoo->blt.dst_y >> 1) * voodoo->blt.dst_stride;
+ dst = (uint16_t *)&voodoo->fb_mem[addr];
+ }
+ else
+ {
+ addr = base_addr + voodoo->blt.dst_y*voodoo->blt.dst_stride;
+ dst = (uint16_t *)&voodoo->fb_mem[addr];
+ }
+
+ if (addr >= voodoo->front_offset && voodoo->row_width)
+ {
+ int y = (addr - voodoo->front_offset) / voodoo->row_width;
+ if (y < voodoo->v_disp)
+ voodoo->dirty_line[y] = 2;
+ }
+
+ while (src_bits && voodoo->blt.cur_x <= voodoo->blt.size_x)
+ {
+ int r = 0, g = 0, b = 0;
+ uint16_t src_dat = 0, dst_dat;
+ int x = (voodoo->blt.x_dir > 0) ? (voodoo->blt.dst_x + voodoo->blt.cur_x) : (voodoo->blt.dst_x - voodoo->blt.cur_x);
+ int rop = 0;
+
+ switch (voodoo->bltCommand & BLIT_SRC_FORMAT)
+ {
+ case BLIT_SRC_1BPP: case BLIT_SRC_1BPP_BYTE_PACKED:
+ src_dat = (data & 1) ? voodoo->bltColorFg : voodoo->bltColorBg;
+ data >>= 1;
+ src_bits--;
+ break;
+ case BLIT_SRC_16BPP:
+ switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT)
+ {
+ case BLIT_SRC_RGB_ARGB: case BLIT_SRC_RGB_RGBA:
+ src_dat = data & 0xffff;
+ break;
+ case BLIT_SRC_RGB_ABGR: case BLIT_SRC_RGB_BGRA:
+ src_dat = ((data & 0xf800) >> 11) | (data & 0x07c0) | ((data & 0x0038) << 11);
+ break;
+ }
+ data >>= 16;
+ src_bits -= 16;
+ break;
+ case BLIT_SRC_24BPP: case BLIT_SRC_24BPP_DITHER_2X2: case BLIT_SRC_24BPP_DITHER_4X4:
+ switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT)
+ {
+ case BLIT_SRC_RGB_ARGB:
+ r = (data >> 16) & 0xff;
+ g = (data >> 8) & 0xff;
+ b = data & 0xff;
+ break;
+ case BLIT_SRC_RGB_ABGR:
+ r = data & 0xff;
+ g = (data >> 8) & 0xff;
+ b = (data >> 16) & 0xff;
+ break;
+ case BLIT_SRC_RGB_RGBA:
+ r = (data >> 24) & 0xff;
+ g = (data >> 16) & 0xff;
+ b = (data >> 8) & 0xff;
+ break;
+ case BLIT_SRC_RGB_BGRA:
+ r = (data >> 8) & 0xff;
+ g = (data >> 16) & 0xff;
+ b = (data >> 24) & 0xff;
+ break;
+ }
+ switch (voodoo->bltCommand & BLIT_SRC_FORMAT)
+ {
+ case BLIT_SRC_24BPP:
+ src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
+ break;
+ case BLIT_SRC_24BPP_DITHER_2X2:
+ r = dither_rb2x2[r][voodoo->blt.dst_y & 1][x & 1];
+ g = dither_g2x2[g][voodoo->blt.dst_y & 1][x & 1];
+ b = dither_rb2x2[b][voodoo->blt.dst_y & 1][x & 1];
+ src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
+ break;
+ case BLIT_SRC_24BPP_DITHER_4X4:
+ r = dither_rb[r][voodoo->blt.dst_y & 3][x & 3];
+ g = dither_g[g][voodoo->blt.dst_y & 3][x & 3];
+ b = dither_rb[b][voodoo->blt.dst_y & 3][x & 3];
+ src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
+ break;
+ }
+ src_bits = 0;
+ break;
+ }
+
+ if (SLI_ENABLED)
+ {
+ if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) ||
+ ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1)))
+ goto skip_pixel;
+ }
+
+ if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED)
+ {
+ if (x < voodoo->bltClipLeft || x >= voodoo->bltClipRight ||
+ voodoo->blt.dst_y < voodoo->bltClipLowY || voodoo->blt.dst_y >= voodoo->bltClipHighY)
+ goto skip_pixel;
+ }
+
+ dst_dat = dst[x];
+
+ if (voodoo->bltCommand & BLIT_SRC_CHROMA)
+ {
+ r = (src_dat >> 11);
+ g = (src_dat >> 5) & 0x3f;
+ b = src_dat & 0x1f;
+
+ if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR &&
+ g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG &&
+ b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB)
+ rop |= BLIT_ROP_SRC_PASS;
+ }
+ if (voodoo->bltCommand & BLIT_DST_CHROMA)
+ {
+ r = (dst_dat >> 11);
+ g = (dst_dat >> 5) & 0x3f;
+ b = dst_dat & 0x1f;
+
+ if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR &&
+ g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG &&
+ b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB)
+ rop |= BLIT_ROP_DST_PASS;
+ }
+
+ MIX(src_dat, dst_dat, voodoo->bltRop[rop]);
+
+ dst[x] = dst_dat;
+
+skip_pixel:
+ voodoo->blt.cur_x++;
+ }
+
+ if (voodoo->blt.cur_x > voodoo->blt.size_x)
+ {
+ voodoo->blt.size_y--;
+ if (voodoo->blt.size_y >= 0)
+ {
+ voodoo->blt.cur_x = 0;
+ voodoo->blt.dst_y += voodoo->blt.y_dir;
+ }
+ }
+}
+
+
+void voodoo_fastfill(voodoo_t *voodoo, voodoo_params_t *params)
+{
+ int y;
+ int low_y, high_y;
+
+ if (params->fbzMode & (1 << 17))
+ {
+ int y_origin = (voodoo->type >= VOODOO_BANSHEE) ? (voodoo->y_origin_swap+1) : voodoo->v_disp;
+
+ high_y = y_origin - params->clipLowY;
+ low_y = y_origin - params->clipHighY;
+ }
+ else
+ {
+ low_y = params->clipLowY;
+ high_y = params->clipHighY;
+ }
+
+ if (params->fbzMode & FBZ_RGB_WMASK)
+ {
+ int r, g, b;
+ uint16_t col;
+
+ r = ((params->color1 >> 16) >> 3) & 0x1f;
+ g = ((params->color1 >> 8) >> 2) & 0x3f;
+ b = (params->color1 >> 3) & 0x1f;
+ col = b | (g << 5) | (r << 11);
+
+ if (SLI_ENABLED)
+ {
+ for (y = low_y; y < high_y; y += 2)
+ {
+ uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask];
+ int x;
+
+ for (x = params->clipLeft; x < params->clipRight; x++)
+ cbuf[x] = col;
+ }
+ }
+ else
+ {
+ for (y = low_y; y < high_y; y++)
+ {
+ if (voodoo->col_tiled)
+ {
+ uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + (y >> 5) * voodoo->row_width + (y & 31) * 128) & voodoo->fb_mask];
+ int x;
+
+ for (x = params->clipLeft; x < params->clipRight; x++)
+ {
+ int x2 = (x & 63) | ((x >> 6) * 128*32/2);
+ cbuf[x2] = col;
+ }
+ }
+ else
+ {
+ uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + y * voodoo->row_width) & voodoo->fb_mask];
+ int x;
+
+ for (x = params->clipLeft; x < params->clipRight; x++)
+ cbuf[x] = col;
+ }
+ }
+ }
+ }
+ if (params->fbzMode & FBZ_DEPTH_WMASK)
+ {
+ if (SLI_ENABLED)
+ {
+ for (y = low_y; y < high_y; y += 2)
+ {
+ uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask];
+ int x;
+
+ for (x = params->clipLeft; x < params->clipRight; x++)
+ abuf[x] = params->zaColor & 0xffff;
+ }
+ }
+ else
+ {
+ for (y = low_y; y < high_y; y++)
+ {
+ if (voodoo->aux_tiled)
+ {
+ uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (y >> 5) * voodoo->aux_row_width + (y & 31) * 128) & voodoo->fb_mask];
+ int x;
+
+ for (x = params->clipLeft; x < params->clipRight; x++)
+ {
+ int x2 = (x & 63) | ((x >> 6) * 128*32/2);
+ abuf[x2] = params->zaColor & 0xffff;
+ }
+ }
+ else
+ {
+ uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + y * voodoo->aux_row_width) & voodoo->fb_mask];
+ int x;
+
+ for (x = params->clipLeft; x < params->clipRight; x++)
+ abuf[x] = params->zaColor & 0xffff;
+ }
+ }
+ }
+ }
+}
diff --git a/src/vid_voodoo_blitter.h b/src/vid_voodoo_blitter.h
new file mode 100644
index 0000000..8d315df
--- /dev/null
+++ b/src/vid_voodoo_blitter.h
@@ -0,0 +1,3 @@
+void voodoo_v2_blit_start(voodoo_t *voodoo);
+void voodoo_v2_blit_data(voodoo_t *voodoo, uint32_t data);
+void voodoo_fastfill(voodoo_t *voodoo, voodoo_params_t *params);
diff --git a/src/vid_voodoo_codegen_x86-64.h b/src/vid_voodoo_codegen_x86-64.h
index d729231..0177631 100644
--- a/src/vid_voodoo_codegen_x86-64.h
+++ b/src/vid_voodoo_codegen_x86-64.h
@@ -34,43 +34,50 @@ typedef struct voodoo_x86_data_t
uint32_t textureMode[2];
uint32_t tLOD[2];
uint32_t trexInit1;
+ int is_tiled;
} voodoo_x86_data_t;
//static voodoo_x86_data_t voodoo_x86_data[2][BLOCK_NUM];
-static int last_block[2] = {0, 0};
-static int next_block_to_write[2] = {0, 0};
+static int last_block[4] = {0, 0};
+static int next_block_to_write[4] = {0, 0};
-#define addbyte(val) \
- code_block[block_pos++] = val; \
- if (block_pos >= BLOCK_SIZE) \
- fatal("Over!\n")
+#define addbyte(val) \
+ do { \
+ code_block[block_pos++] = val; \
+ if (block_pos >= BLOCK_SIZE) \
+ fatal("Over!\n"); \
+ } while (0)
-#define addword(val) \
- *(uint16_t *)&code_block[block_pos] = val; \
- block_pos += 2; \
- if (block_pos >= BLOCK_SIZE) \
- fatal("Over!\n")
+#define addword(val) \
+ do { \
+ *(uint16_t *)&code_block[block_pos] = val; \
+ block_pos += 2; \
+ if (block_pos >= BLOCK_SIZE) \
+ fatal("Over!\n"); \
+ } while (0)
-#define addlong(val) \
- *(uint32_t *)&code_block[block_pos] = val; \
- block_pos += 4; \
- if (block_pos >= BLOCK_SIZE) \
- fatal("Over!\n")
+#define addlong(val) \
+ do { \
+ *(uint32_t *)&code_block[block_pos] = val; \
+ block_pos += 4; \
+ if (block_pos >= BLOCK_SIZE) \
+ fatal("Over!\n"); \
+ } while (0)
-#define addquad(val) \
- *(uint64_t *)&code_block[block_pos] = val; \
- block_pos += 8; \
- if (block_pos >= BLOCK_SIZE) \
- fatal("Over!\n")
+#define addquad(val) \
+ do { \
+ *(uint64_t *)&code_block[block_pos] = val; \
+ block_pos += 8; \
+ if (block_pos >= BLOCK_SIZE) \
+ fatal("Over!\n"); \
+ } while (0)
static __m128i xmm_01_w;// = 0x0001000100010001ull;
static __m128i xmm_ff_w;// = 0x00ff00ff00ff00ffull;
static __m128i xmm_ff_b;// = 0x00000000ffffffffull;
-static uint32_t zero = 0;
-
static __m128i alookup[257], aminuslookup[256];
static __m128i minus_254;// = 0xff02ff02ff02ff02ull;
static __m128i bilinear_lookup[256*2];
@@ -784,6 +791,28 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
addbyte(0x4c); /*MOV RSI, R15*/
addbyte(0x89);
addbyte(0xfe);
+ if (params->col_tiled || params->aux_tiled)
+ {
+ addbyte(0x8b); /*MOV EAX, state->x[EDI]*/
+ addbyte(0x87);
+ addlong(offsetof(voodoo_state_t, x));
+ addbyte(0x89); /*MOV EBX, EAX*/
+ addbyte(0xc3);
+ addbyte(0x83); /*AND EAX, 63*/
+ addbyte(0xe0);
+ addbyte(63);
+ addbyte(0xc1); /*SHR EBX, 6*/
+ addbyte(0xeb);
+ addbyte(6);
+ addbyte(0xc1); /*SHL EBX, 11 - tile is 128*32, << 12, div 2 because word index*/
+ addbyte(0xe3);
+ addbyte(11);
+ addbyte(0x01); /*ADD EAX, EBX*/
+ addbyte(0xd8);
+ addbyte(0x89); /*MOV state->x_tiled[EDI], EAX*/
+ addbyte(0x87);
+ addlong(offsetof(voodoo_state_t, x_tiled));
+ }
addbyte(0x66); /*PXOR XMM2, XMM2*/
addbyte(0x0f);
addbyte(0xef);
@@ -901,7 +930,10 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
{
addbyte(0x8b); /*MOV EBX, state->x[EDI]*/
addbyte(0x9f);
- addlong(offsetof(voodoo_state_t, x));
+ if (params->aux_tiled)
+ addlong(offsetof(voodoo_state_t, x_tiled));
+ else
+ addlong(offsetof(voodoo_state_t, x));
addbyte(0x48); /*MOV RCX, aux_mem[RDI]*/
addbyte(0x8b);
addbyte(0x8f);
@@ -1701,10 +1733,44 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
if ((params->fbzMode & FBZ_CHROMAKEY))
{
- addbyte(0x66); /*MOVD EAX, XMM0*/
- addbyte(0x0f);
- addbyte(0x7e);
- addbyte(0xc0);
+ switch (_rgb_sel)
+ {
+ case CC_LOCALSELECT_ITER_RGB:
+ addbyte(0xf3); /*MOVDQU XMM0, ib*/ /* ir, ig and ib must be in same dqword!*/
+ addbyte(0x0f);
+ addbyte(0x6f);
+ addbyte(0x87);
+ addlong(offsetof(voodoo_state_t, ib));
+ addbyte(0x66); /*PSRAD XMM0, 12*/
+ addbyte(0x0f);
+ addbyte(0x72);
+ addbyte(0xe0);
+ addbyte(12);
+ addbyte(0x66); /*PACKSSDW XMM0, XMM0*/
+ addbyte(0x0f);
+ addbyte(0x6b);
+ addbyte(0xc0);
+ addbyte(0x66); /*PACKUSWB XMM0, XMM0*/
+ addbyte(0x0f);
+ addbyte(0x67);
+ addbyte(0xc0);
+ addbyte(0x66); /*MOVD EAX, XMM0*/
+ addbyte(0x0f);
+ addbyte(0x7e);
+ addbyte(0xc0);
+ break;
+ case CC_LOCALSELECT_COLOR1:
+ addbyte(0x8b); /*MOV EAX, params->color1[RSI]*/
+ addbyte(0x86);
+ addlong(offsetof(voodoo_params_t, color1));
+ break;
+ case CC_LOCALSELECT_TEX:
+ addbyte(0x66); /*MOVD EAX, XMM0*/
+ addbyte(0x0f);
+ addbyte(0x7e);
+ addbyte(0xc0);
+ break;
+ }
addbyte(0x8b); /*MOV EBX, params->chromaKey[ESI]*/
addbyte(0x9e);
addlong(offsetof(voodoo_params_t, chromaKey));
@@ -2485,7 +2551,10 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
addquad((uintptr_t)rgb565);
addbyte(0x8b); /*MOV EAX, state->x[EDI]*/
addbyte(0x87);
- addlong(offsetof(voodoo_state_t, x));
+ if (params->col_tiled)
+ addlong(offsetof(voodoo_state_t, x_tiled));
+ else
+ addlong(offsetof(voodoo_state_t, x));
addbyte(0x48); /*MOV RBP, fb_mem*/
addbyte(0x8b);
addbyte(0xaf);
@@ -2867,8 +2936,11 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
addbyte(0x8b); /*MOV EDX, state->x[EDI]*/
addbyte(0x97);
- addlong(offsetof(voodoo_state_t, x));
-
+ if (params->col_tiled)
+ addlong(offsetof(voodoo_state_t, x_tiled));
+ else
+ addlong(offsetof(voodoo_state_t, x));
+
addbyte(0x66); /*MOV EAX, XMM0*/
addbyte(0x0f);
addbyte(0x7e);
@@ -2934,7 +3006,10 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
}
addbyte(0x8b); /*MOV EDX, state->x[EDI]*/
addbyte(0x97);
- addlong(offsetof(voodoo_state_t, x));
+ if (params->col_tiled)
+ addlong(offsetof(voodoo_state_t, x_tiled));
+ else
+ addlong(offsetof(voodoo_state_t, x));
addbyte(0x4c); /*ADD RSI, R8*/
addbyte(0x01);
addbyte(0xc6);
@@ -3020,6 +3095,12 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE))
{
+ addbyte(0x8b); /*MOV EDX, state->x[EDI]*/
+ addbyte(0x97);
+ if (params->aux_tiled)
+ addlong(offsetof(voodoo_state_t, x_tiled));
+ else
+ addlong(offsetof(voodoo_state_t, x));
addbyte(0x66); /*MOV AX, new_depth*/
addbyte(0x8b);
addbyte(0x87);
@@ -3290,7 +3371,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
addbyte(0xC3); /*RET*/
}
-static int voodoo_recomp = 0;
+int voodoo_recomp = 0;
static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int odd_even)
{
int c;
@@ -3300,7 +3381,7 @@ static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params,
for (c = 0; c < 8; c++)
{
- data = &voodoo_x86_data[odd_even + c*2]; //&voodoo_x86_data[odd_even][b];
+ data = &voodoo_x86_data[odd_even + c*4]; //&voodoo_x86_data[odd_even][b];
if (state->xdir == data->xdir &&
params->alphaMode == data->alphaMode &&
@@ -3311,7 +3392,8 @@ static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params,
params->textureMode[0] == data->textureMode[0] &&
params->textureMode[1] == data->textureMode[1] &&
(params->tLOD[0] & LOD_MASK) == data->tLOD[0] &&
- (params->tLOD[1] & LOD_MASK) == data->tLOD[1])
+ (params->tLOD[1] & LOD_MASK) == data->tLOD[1] &&
+ ((params->col_tiled || params->aux_tiled) ? 1 : 0) == data->is_tiled)
{
last_block[odd_even] = b;
return data->code_block;
@@ -3320,7 +3402,7 @@ static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params,
b = (b + 1) & 7;
}
voodoo_recomp++;
- data = &voodoo_x86_data[odd_even + next_block_to_write[odd_even]*2];
+ data = &voodoo_x86_data[odd_even + next_block_to_write[odd_even]*4];
// code_block = data->code_block;
voodoo_generate(data->code_block, voodoo, params, state, depth_op);
@@ -3335,36 +3417,21 @@ voodoo_recomp++;
data->textureMode[1] = params->textureMode[1];
data->tLOD[0] = params->tLOD[0] & LOD_MASK;
data->tLOD[1] = params->tLOD[1] & LOD_MASK;
+ data->is_tiled = (params->col_tiled || params->aux_tiled) ? 1 : 0;
next_block_to_write[odd_even] = (next_block_to_write[odd_even] + 1) & 7;
return data->code_block;
}
-static void voodoo_codegen_init(voodoo_t *voodoo)
+void voodoo_codegen_init(voodoo_t *voodoo)
{
int c;
-#if defined(__linux__) || defined(__APPLE__)
- void *start;
- size_t len;
- long pagesize = sysconf(_SC_PAGESIZE);
- long pagemask = ~(pagesize - 1);
-#endif
#if WIN64
- voodoo->codegen_data = VirtualAlloc(NULL, sizeof(voodoo_x86_data_t) * BLOCK_NUM * 2, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ voodoo->codegen_data = VirtualAlloc(NULL, sizeof(voodoo_x86_data_t) * BLOCK_NUM * 4, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#else
- voodoo->codegen_data = malloc(sizeof(voodoo_x86_data_t) * BLOCK_NUM * 2);
-#endif
-
-#if defined(__linux__) || defined(__APPLE__)
- start = (void *)((long)voodoo->codegen_data & pagemask);
- len = ((sizeof(voodoo_x86_data_t) * BLOCK_NUM * 2) + pagesize) & pagemask;
- if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
- {
- perror("mprotect");
- exit(-1);
- }
+ voodoo->codegen_data = mmap(0, sizeof(voodoo_x86_data_t) * BLOCK_NUM*4, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 0);
#endif
for (c = 0; c < 256; c++)
@@ -3389,12 +3456,12 @@ static void voodoo_codegen_init(voodoo_t *voodoo)
xmm_00_ff_w[1] = _mm_set_epi32(0, 0, 0xff | (0xff << 16), 0xff | (0xff << 16));
}
-static void voodoo_codegen_close(voodoo_t *voodoo)
+void voodoo_codegen_close(voodoo_t *voodoo)
{
#if WIN64
VirtualFree(voodoo->codegen_data, 0, MEM_RELEASE);
#else
- free(voodoo->codegen_data);
+ munmap(voodoo->codegen_data, sizeof(voodoo_x86_data_t) * BLOCK_NUM*4);
#endif
}
diff --git a/src/vid_voodoo_codegen_x86.h b/src/vid_voodoo_codegen_x86.h
index 48b0cca..3721f70 100644
--- a/src/vid_voodoo_codegen_x86.h
+++ b/src/vid_voodoo_codegen_x86.h
@@ -34,33 +34,42 @@ typedef struct voodoo_x86_data_t
uint32_t textureMode[2];
uint32_t tLOD[2];
uint32_t trexInit1;
+ int is_tiled;
} voodoo_x86_data_t;
-static int last_block[2] = {0, 0};
-static int next_block_to_write[2] = {0, 0};
+static int last_block[4] = {0, 0};
+static int next_block_to_write[4] = {0, 0};
-#define addbyte(val) \
- code_block[block_pos++] = val; \
- if (block_pos >= BLOCK_SIZE) \
- fatal("Over!\n")
+#define addbyte(val) \
+ do { \
+ code_block[block_pos++] = val; \
+ if (block_pos >= BLOCK_SIZE) \
+ fatal("Over!\n"); \
+ } while (0)
-#define addword(val) \
- *(uint16_t *)&code_block[block_pos] = val; \
- block_pos += 2; \
- if (block_pos >= BLOCK_SIZE) \
- fatal("Over!\n")
+#define addword(val) \
+ do { \
+ *(uint16_t *)&code_block[block_pos] = val; \
+ block_pos += 2; \
+ if (block_pos >= BLOCK_SIZE) \
+ fatal("Over!\n"); \
+ } while (0)
-#define addlong(val) \
- *(uint32_t *)&code_block[block_pos] = val; \
- block_pos += 4; \
- if (block_pos >= BLOCK_SIZE) \
- fatal("Over!\n")
+#define addlong(val) \
+ do { \
+ *(uint32_t *)&code_block[block_pos] = val; \
+ block_pos += 4; \
+ if (block_pos >= BLOCK_SIZE) \
+ fatal("Over!\n"); \
+ } while (0)
-#define addquad(val) \
- *(uint64_t *)&code_block[block_pos] = val; \
- block_pos += 8; \
- if (block_pos >= BLOCK_SIZE) \
- fatal("Over!\n")
+#define addquad(val) \
+ do { \
+ *(uint64_t *)&code_block[block_pos] = val; \
+ block_pos += 8; \
+ if (block_pos >= BLOCK_SIZE) \
+ fatal("Over!\n"); \
+ } while (0)
static __m128i xmm_01_w;// = 0x0001000100010001ull;
@@ -694,6 +703,28 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
addbyte(0x74);
addbyte(0x24);
addbyte(8+16);
+ if (params->col_tiled || params->aux_tiled)
+ {
+ addbyte(0x8b); /*MOV EAX, state->x[EDI]*/
+ addbyte(0x87);
+ addlong(offsetof(voodoo_state_t, x));
+ addbyte(0x89); /*MOV EBX, EAX*/
+ addbyte(0xc3);
+ addbyte(0x83); /*AND EAX, 63*/
+ addbyte(0xe0);
+ addbyte(63);
+ addbyte(0xc1); /*SHR EBX, 6*/
+ addbyte(0xeb);
+ addbyte(6);
+ addbyte(0xc1); /*SHL EBX, 11 - tile is 128*32, << 12, div 2 because word index*/
+ addbyte(0xe3);
+ addbyte(11);
+ addbyte(0x01); /*ADD EAX, EBX*/
+ addbyte(0xd8);
+ addbyte(0x89); /*MOV state->x_tiled[EDI], EAX*/
+ addbyte(0x87);
+ addlong(offsetof(voodoo_state_t, x_tiled));
+ }
addbyte(0x66); /*PXOR XMM2, XMM2*/
addbyte(0x0f);
addbyte(0xef);
@@ -826,7 +857,10 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
{
addbyte(0x8b); /*MOV EBX, state->x[EDI]*/
addbyte(0x9f);
- addlong(offsetof(voodoo_state_t, x));
+ if (params->aux_tiled)
+ addlong(offsetof(voodoo_state_t, x_tiled));
+ else
+ addlong(offsetof(voodoo_state_t, x));
addbyte(0x8b);/*MOV ECX, aux_mem[EDI]*/
addbyte(0x8f);
addlong(offsetof(voodoo_state_t, aux_mem));
@@ -1634,10 +1668,44 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
if ((params->fbzMode & FBZ_CHROMAKEY))
{
- addbyte(0x66); /*MOVD EAX, XMM0*/
- addbyte(0x0f);
- addbyte(0x7e);
- addbyte(0xc0);
+ switch (_rgb_sel)
+ {
+ case CC_LOCALSELECT_ITER_RGB:
+ addbyte(0xf3); /*MOVDQU XMM0, ib*/ /* ir, ig and ib must be in same dqword!*/
+ addbyte(0x0f);
+ addbyte(0x6f);
+ addbyte(0x87);
+ addlong(offsetof(voodoo_state_t, ib));
+ addbyte(0x66); /*PSRAD XMM0, 12*/
+ addbyte(0x0f);
+ addbyte(0x72);
+ addbyte(0xe0);
+ addbyte(12);
+ addbyte(0x66); /*PACKSSDW XMM0, XMM0*/
+ addbyte(0x0f);
+ addbyte(0x6b);
+ addbyte(0xc0);
+ addbyte(0x66); /*PACKUSWB XMM0, XMM0*/
+ addbyte(0x0f);
+ addbyte(0x67);
+ addbyte(0xc0);
+ addbyte(0x66); /*MOVD EAX, XMM0*/
+ addbyte(0x0f);
+ addbyte(0x7e);
+ addbyte(0xc0);
+ break;
+ case CC_LOCALSELECT_COLOR1:
+ addbyte(0x8b); /*MOV EAX, params->color1[ESI]*/
+ addbyte(0x86);
+ addlong(offsetof(voodoo_params_t, color1));
+ break;
+ case CC_LOCALSELECT_TEX:
+ addbyte(0x66); /*MOVD EAX, XMM0*/
+ addbyte(0x0f);
+ addbyte(0x7e);
+ addbyte(0xc0);
+ break;
+ }
addbyte(0x8b); /*MOV EBX, params->chromaKey[ESI]*/
addbyte(0x9e);
addlong(offsetof(voodoo_params_t, chromaKey));
@@ -2436,7 +2504,10 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
{
addbyte(0x8b); /*MOV EAX, state->x[EDI]*/
addbyte(0x87);
- addlong(offsetof(voodoo_state_t, x));
+ if (params->col_tiled)
+ addlong(offsetof(voodoo_state_t, x_tiled));
+ else
+ addlong(offsetof(voodoo_state_t, x));
addbyte(0x8b); /*MOV EBP, fb_mem*/
addbyte(0xaf);
addlong(offsetof(voodoo_state_t, fb_mem));
@@ -2815,8 +2886,11 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
addbyte(0x8b); /*MOV EDX, state->x[EDI]*/
addbyte(0x97);
- addlong(offsetof(voodoo_state_t, x));
-
+ if (params->col_tiled)
+ addlong(offsetof(voodoo_state_t, x_tiled));
+ else
+ addlong(offsetof(voodoo_state_t, x));
+
addbyte(0x66); /*MOV EAX, XMM0*/
addbyte(0x0f);
addbyte(0x7e);
@@ -2884,7 +2958,10 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
}
addbyte(0x8b); /*MOV EDX, state->x[EDI]*/
addbyte(0x97);
- addlong(offsetof(voodoo_state_t, x));
+ if (params->col_tiled)
+ addlong(offsetof(voodoo_state_t, x_tiled));
+ else
+ addlong(offsetof(voodoo_state_t, x));
if (dither2x2)
{
addbyte(0xc1); /*SHL ECX, 2*/
@@ -2968,6 +3045,12 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE))
{
+ addbyte(0x8b); /*MOV EDX, state->x[EDI]*/
+ addbyte(0x97);
+ if (params->aux_tiled)
+ addlong(offsetof(voodoo_state_t, x_tiled));
+ else
+ addlong(offsetof(voodoo_state_t, x));
addbyte(0x66); /*MOV AX, new_depth*/
addbyte(0x8b);
addbyte(0x87);
@@ -3227,7 +3310,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
if (params->textureMode[1] & TEXTUREMODE_TRILINEAR)
cs = cs;
}
-static int voodoo_recomp = 0;
+int voodoo_recomp = 0;
static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int odd_even)
{
@@ -3238,7 +3321,7 @@ static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params,
for (c = 0; c < 8; c++)
{
- data = &codegen_data[odd_even + b*2];
+ data = &codegen_data[odd_even + b*4];
if (state->xdir == data->xdir &&
params->alphaMode == data->alphaMode &&
@@ -3249,7 +3332,8 @@ static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params,
params->textureMode[0] == data->textureMode[0] &&
params->textureMode[1] == data->textureMode[1] &&
(params->tLOD[0] & LOD_MASK) == data->tLOD[0] &&
- (params->tLOD[1] & LOD_MASK) == data->tLOD[1])
+ (params->tLOD[1] & LOD_MASK) == data->tLOD[1] &&
+ ((params->col_tiled || params->aux_tiled) ? 1 : 0) == data->is_tiled)
{
last_block[odd_even] = b;
return data->code_block;
@@ -3258,7 +3342,7 @@ static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params,
b = (b + 1) & 7;
}
voodoo_recomp++;
- data = &codegen_data[odd_even + next_block_to_write[odd_even]*2];
+ data = &codegen_data[odd_even + next_block_to_write[odd_even]*4];
// code_block = data->code_block;
voodoo_generate(data->code_block, voodoo, params, state, depth_op);
@@ -3273,13 +3357,14 @@ voodoo_recomp++;
data->textureMode[1] = params->textureMode[1];
data->tLOD[0] = params->tLOD[0] & LOD_MASK;
data->tLOD[1] = params->tLOD[1] & LOD_MASK;
+ data->is_tiled = (params->col_tiled || params->aux_tiled) ? 1 : 0;
next_block_to_write[odd_even] = (next_block_to_write[odd_even] + 1) & 7;
return data->code_block;
}
-static void voodoo_codegen_init(voodoo_t *voodoo)
+void voodoo_codegen_init(voodoo_t *voodoo)
{
int c;
#if defined(__linux__) || defined(__APPLE__)
@@ -3290,19 +3375,9 @@ static void voodoo_codegen_init(voodoo_t *voodoo)
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
- voodoo->codegen_data = VirtualAlloc(NULL, sizeof(voodoo_x86_data_t) * BLOCK_NUM*2, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ voodoo->codegen_data = VirtualAlloc(NULL, sizeof(voodoo_x86_data_t) * BLOCK_NUM*4, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#else
- voodoo->codegen_data = malloc(sizeof(voodoo_x86_data_t) * BLOCK_NUM*2);
-#endif
-
-#if defined(__linux__) || defined(__APPLE__)
- start = (void *)((long)voodoo->codegen_data & pagemask);
- len = ((sizeof(voodoo_x86_data_t) * BLOCK_NUM*2) + pagesize) & pagemask;
- if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
- {
- perror("mprotect");
- exit(-1);
- }
+ voodoo->codegen_data = mmap(0, sizeof(voodoo_x86_data_t) * BLOCK_NUM*4, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 0);
#endif
for (c = 0; c < 256; c++)
@@ -3327,11 +3402,11 @@ static void voodoo_codegen_init(voodoo_t *voodoo)
xmm_00_ff_w[1] = _mm_set_epi32(0, 0, 0xff | (0xff << 16), 0xff | (0xff << 16));
}
-static void voodoo_codegen_close(voodoo_t *voodoo)
+void voodoo_codegen_close(voodoo_t *voodoo)
{
#if defined WIN32 || defined _WIN32 || defined _WIN32
VirtualFree(voodoo->codegen_data, 0, MEM_RELEASE);
#else
- free(voodoo->codegen_data);
+ munmap(voodoo->codegen_data, sizeof(voodoo_x86_data_t) * BLOCK_NUM*4);
#endif
}
diff --git a/src/vid_voodoo_common.h b/src/vid_voodoo_common.h
new file mode 100644
index 0000000..bfd0f7f
--- /dev/null
+++ b/src/vid_voodoo_common.h
@@ -0,0 +1,512 @@
+#ifdef MIN
+#undef MIN
+#endif
+#ifdef CLAMP
+#undef CLAMP
+#endif
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+#define CLAMP(x) (((x) < 0) ? 0 : (((x) > 0xff) ? 0xff : (x)))
+#define CLAMP16(x) (((x) < 0) ? 0 : (((x) > 0xffff) ? 0xffff : (x)))
+
+
+#define LOD_MAX 8
+
+#define TEX_DIRTY_SHIFT 10
+
+#define TEX_CACHE_MAX 64
+
+enum
+{
+ VOODOO_1 = 0,
+ VOODOO_SB50,
+ VOODOO_2,
+ VOODOO_BANSHEE,
+ VOODOO_3
+};
+
+typedef union int_float
+{
+ uint32_t i;
+ float f;
+} int_float;
+
+typedef struct rgb_t
+{
+ uint8_t b, g, r;
+ uint8_t pad;
+} rgb_t;
+typedef struct rgba8_t
+{
+ uint8_t b, g, r, a;
+} rgba8_t;
+
+typedef union rgba_u
+{
+ struct
+ {
+ uint8_t b, g, r, a;
+ } rgba;
+ uint32_t u;
+} rgba_u;
+
+#define FIFO_SIZE 65536
+#define FIFO_MASK (FIFO_SIZE - 1)
+#define FIFO_ENTRY_SIZE (1 << 31)
+
+#define FIFO_ENTRIES (voodoo->fifo_write_idx - voodoo->fifo_read_idx)
+#define FIFO_FULL ((voodoo->fifo_write_idx - voodoo->fifo_read_idx) >= FIFO_SIZE-4)
+#define FIFO_EMPTY (voodoo->fifo_read_idx == voodoo->fifo_write_idx)
+
+#define FIFO_TYPE 0xff000000
+#define FIFO_ADDR 0x00ffffff
+
+enum
+{
+ FIFO_INVALID = (0x00 << 24),
+ FIFO_WRITEL_REG = (0x01 << 24),
+ FIFO_WRITEW_FB = (0x02 << 24),
+ FIFO_WRITEL_FB = (0x03 << 24),
+ FIFO_WRITEL_TEX = (0x04 << 24),
+ FIFO_WRITEL_2DREG = (0x05 << 24)
+};
+
+#define PARAM_SIZE 1024
+#define PARAM_MASK (PARAM_SIZE - 1)
+#define PARAM_ENTRY_SIZE (1 << 31)
+
+#define PARAM_ENTRIES(x) (voodoo->params_write_idx - voodoo->params_read_idx[x])
+#define PARAM_FULL(x) ((voodoo->params_write_idx - voodoo->params_read_idx[x]) >= PARAM_SIZE)
+#define PARAM_EMPTY(x) (voodoo->params_read_idx[x] == voodoo->params_write_idx)
+
+typedef struct
+{
+ uint32_t addr_type;
+ uint32_t val;
+} fifo_entry_t;
+
+typedef struct voodoo_params_t
+{
+ int command;
+
+ int32_t vertexAx, vertexAy, vertexBx, vertexBy, vertexCx, vertexCy;
+
+ uint32_t startR, startG, startB, startZ, startA;
+
+ int32_t dBdX, dGdX, dRdX, dAdX, dZdX;
+
+ int32_t dBdY, dGdY, dRdY, dAdY, dZdY;
+
+ int64_t startW, dWdX, dWdY;
+
+ struct
+ {
+ int64_t startS, startT, startW, p1;
+ int64_t dSdX, dTdX, dWdX, p2;
+ int64_t dSdY, dTdY, dWdY, p3;
+ } tmu[2];
+
+ uint32_t color0, color1;
+
+ uint32_t fbzMode;
+ uint32_t fbzColorPath;
+
+ uint32_t fogMode;
+ rgb_t fogColor;
+ struct
+ {
+ uint8_t fog, dfog;
+ } fogTable[64];
+
+ uint32_t alphaMode;
+
+ uint32_t zaColor;
+
+ int chromaKey_r, chromaKey_g, chromaKey_b;
+ uint32_t chromaKey;
+
+ uint32_t textureMode[2];
+ uint32_t tLOD[2];
+
+ uint32_t texBaseAddr[2], texBaseAddr1[2], texBaseAddr2[2], texBaseAddr38[2];
+
+ uint32_t tex_base[2][LOD_MAX+2];
+ uint32_t tex_end[2][LOD_MAX+2];
+ int tex_width[2];
+ int tex_w_mask[2][LOD_MAX+2];
+ int tex_w_nmask[2][LOD_MAX+2];
+ int tex_h_mask[2][LOD_MAX+2];
+ int tex_shift[2][LOD_MAX+2];
+ int tex_lod[2][LOD_MAX+2];
+ int tex_entry[2];
+ int detail_max[2], detail_bias[2], detail_scale[2];
+
+ uint32_t draw_offset, aux_offset;
+
+ int tformat[2];
+
+ int clipLeft, clipRight, clipLowY, clipHighY;
+ int clipLeft1, clipRight1, clipLowY1, clipHighY1;
+
+ int sign;
+
+ uint32_t front_offset;
+
+ uint32_t swapbufferCMD;
+
+ uint32_t stipple;
+
+ int col_tiled, aux_tiled;
+ int row_width, aux_row_width;
+} voodoo_params_t;
+
+typedef struct texture_t
+{
+ uint32_t base;
+ uint32_t tLOD;
+ volatile int refcount, refcount_r[4];
+ int is16;
+ uint32_t palette_checksum;
+ uint32_t addr_start[4], addr_end[4];
+ uint32_t *data;
+} texture_t;
+
+typedef struct vert_t
+{
+ float sVx, sVy;
+ float sRed, sGreen, sBlue, sAlpha;
+ float sVz, sWb;
+ float sW0, sS0, sT0;
+ float sW1, sS1, sT1;
+} vert_t;
+
+typedef struct clip_t
+{
+ int x_min, x_max;
+ int y_min, y_max;
+} clip_t;
+
+typedef struct voodoo_t
+{
+ mem_mapping_t mapping;
+
+ int pci_enable;
+
+ uint8_t dac_data[8];
+ int dac_reg, dac_reg_ff;
+ uint8_t dac_readdata;
+ uint16_t dac_pll_regs[16];
+
+ float pixel_clock;
+ uint64_t line_time;
+
+ voodoo_params_t params;
+
+ uint32_t fbiInit0, fbiInit1, fbiInit2, fbiInit3, fbiInit4;
+ uint32_t fbiInit5, fbiInit6, fbiInit7; /*Voodoo 2*/
+
+ uint32_t initEnable;
+
+ uint32_t lfbMode;
+
+ uint32_t memBaseAddr;
+
+ int_float fvertexAx, fvertexAy, fvertexBx, fvertexBy, fvertexCx, fvertexCy;
+
+ uint32_t front_offset, back_offset;
+
+ uint32_t fb_read_offset, fb_write_offset;
+
+ int row_width, aux_row_width;
+ int block_width;
+
+ int col_tiled, aux_tiled;
+
+ uint8_t *fb_mem, *tex_mem[2];
+ uint16_t *tex_mem_w[2];
+
+ int rgb_sel;
+
+ uint32_t trexInit1[2];
+
+ uint32_t tmuConfig;
+
+ mutex_t *swap_mutex;
+ int swap_count;
+
+ int disp_buffer, draw_buffer;
+ pc_timer_t timer;
+
+ int line;
+ svga_t *svga;
+
+ uint32_t backPorch;
+ uint32_t videoDimensions;
+ uint32_t hSync, vSync;
+
+ int h_total, v_total, v_disp;
+ int h_disp;
+ int v_retrace;
+
+ struct
+ {
+ uint32_t y[4], i[4], q[4];
+ } nccTable[2][2];
+
+ rgba_u palette[2][256];
+
+ rgba_u ncc_lookup[2][2][256];
+ int ncc_dirty[2];
+
+ thread_t *fifo_thread;
+ thread_t *render_thread[4];
+ event_t *wake_fifo_thread;
+ event_t *wake_main_thread;
+ event_t *fifo_not_full_event;
+ event_t *render_not_full_event[4];
+ event_t *wake_render_thread[4];
+
+ int voodoo_busy;
+ int render_voodoo_busy[4];
+
+ int render_threads;
+ int odd_even_mask;
+
+ int pixel_count[4], texel_count[4], tri_count, frame_count;
+ int pixel_count_old[4], texel_count_old[4];
+ int wr_count, rd_count, tex_count;
+
+ int retrace_count;
+ int swap_interval;
+ uint32_t swap_offset;
+ int swap_pending;
+
+ int bilinear_enabled;
+ int dithersub_enabled;
+
+ int fb_size;
+ uint32_t fb_mask;
+
+ int texture_size;
+ uint32_t texture_mask;
+
+ int dual_tmus;
+ int type;
+
+ fifo_entry_t fifo[FIFO_SIZE];
+ volatile int fifo_read_idx, fifo_write_idx;
+ volatile int cmd_read, cmd_written, cmd_written_fifo;
+
+ voodoo_params_t params_buffer[PARAM_SIZE];
+ volatile int params_read_idx[4], params_write_idx;
+
+ uint32_t cmdfifo_base, cmdfifo_end, cmdfifo_size;
+ int cmdfifo_rp, cmdfifo_ret_addr;
+ int cmdfifo_in_sub;
+ volatile int cmdfifo_depth_rd, cmdfifo_depth_wr;
+ volatile int cmdfifo_enabled;
+ uint32_t cmdfifo_amin, cmdfifo_amax;
+ int cmdfifo_holecount;
+
+ uint32_t sSetupMode;
+ vert_t verts[4];
+ unsigned int vertex_ages[3];
+ unsigned int vertex_next_age;
+ int num_verticies;
+ int cull_pingpong;
+
+ int flush;
+
+ int scrfilter;
+ int scrfilterEnabled;
+ int scrfilterThreshold;
+ int scrfilterThresholdOld;
+
+ uint32_t last_write_addr;
+
+ uint32_t fbiPixelsIn;
+ uint32_t fbiChromaFail;
+ uint32_t fbiZFuncFail;
+ uint32_t fbiAFuncFail;
+ uint32_t fbiPixelsOut;
+
+ uint32_t bltSrcBaseAddr;
+ uint32_t bltDstBaseAddr;
+ int bltSrcXYStride, bltDstXYStride;
+ uint32_t bltSrcChromaRange, bltDstChromaRange;
+ int bltSrcChromaMinR, bltSrcChromaMinG, bltSrcChromaMinB;
+ int bltSrcChromaMaxR, bltSrcChromaMaxG, bltSrcChromaMaxB;
+ int bltDstChromaMinR, bltDstChromaMinG, bltDstChromaMinB;
+ int bltDstChromaMaxR, bltDstChromaMaxG, bltDstChromaMaxB;
+
+ int bltClipRight, bltClipLeft;
+ int bltClipHighY, bltClipLowY;
+
+ int bltSrcX, bltSrcY;
+ int bltDstX, bltDstY;
+ int bltSizeX, bltSizeY;
+ int bltRop[4];
+ uint16_t bltColorFg, bltColorBg;
+
+ uint32_t bltCommand;
+
+ uint32_t leftOverlayBuf;
+
+ struct
+ {
+ int dst_x, dst_y;
+ int cur_x;
+ int size_x, size_y;
+ int x_dir, y_dir;
+ int dst_stride;
+ } blt;
+
+ struct
+ {
+ uint32_t bresError0, bresError1;
+ uint32_t clip0Min, clip0Max;
+ uint32_t clip1Min, clip1Max;
+ uint32_t colorBack, colorFore;
+ uint32_t command, commandExtra;
+ uint32_t dstBaseAddr;
+ uint32_t dstFormat;
+ uint32_t dstSize;
+ uint32_t dstXY;
+ uint32_t lineStipple;
+ uint32_t lineStyle;
+ uint32_t rop;
+ uint32_t srcBaseAddr;
+ uint32_t srcFormat;
+ uint32_t srcSize;
+ uint32_t srcXY;
+
+ uint32_t colorPattern[64];
+
+ int bres_error_0, bres_error_1;
+ uint32_t colorPattern8[64], colorPattern16[64], colorPattern24[64];
+ int cur_x, cur_y;
+ uint32_t dstBaseAddr_tiled;
+ uint32_t dstColorkeyMin, dstColorkeyMax;
+ int dstSizeX, dstSizeY;
+ int dstX, dstY;
+ int dst_stride;
+ int patoff_x, patoff_y;
+ uint8_t rops[4];
+ uint32_t srcBaseAddr_tiled;
+ uint32_t srcColorkeyMin, srcColorkeyMax;
+ int srcSizeX, srcSizeY;
+ int srcX, srcY;
+ int src_stride;
+ int old_srcX;
+
+ /*Used for handling packed 24bpp host data*/
+ int host_data_remainder;
+ uint32_t old_host_data;
+
+ /*Polyfill coordinates*/
+ int lx[2], rx[2];
+ int ly[2], ry[2];
+
+ /*Polyfill state*/
+ int error[2];
+ int dx[2], dy[2];
+ int x_inc[2]; /*y_inc is always 1 for polyfill*/
+ int lx_cur, rx_cur;
+
+ clip_t clip[2];
+
+ uint8_t host_data[16384];
+ int host_data_count;
+ int host_data_size_src, host_data_size_dest;
+ int src_stride_src, src_stride_dest;
+
+ int src_bpp;
+
+ int line_pix_pos, line_bit_pos;
+ int line_rep_cnt, line_bit_mask_size;
+ } banshee_blt;
+
+ struct
+ {
+ uint32_t vidOverlayStartCoords;
+ uint32_t vidOverlayEndScreenCoords;
+ uint32_t vidOverlayDudx, vidOverlayDudxOffsetSrcWidth;
+ uint32_t vidOverlayDvdy, vidOverlayDvdyOffset;
+ //uint32_t vidDesktopOverlayStride;
+
+ int start_x, start_y;
+ int end_x, end_y;
+ int size_x, size_y;
+ int overlay_bytes;
+
+ unsigned int src_y;
+ } overlay;
+
+ rgb_t clutData[33];
+ int clutData_dirty;
+ rgb_t clutData256[256];
+ uint32_t video_16to32[0x10000];
+
+ uint8_t dirty_line[2048];
+ int dirty_line_low, dirty_line_high;
+
+ int fb_write_buffer, fb_draw_buffer;
+ int buffer_cutoff;
+
+ uint32_t tile_base, tile_stride;
+ int tile_stride_shift, tile_x, tile_x_real;
+
+ int y_origin_swap;
+
+ int read_time, write_time, burst_time;
+
+ pc_timer_t wake_timer;
+
+ /* screen filter tables */
+ uint8_t thefilter[256][256];
+ uint8_t thefilterg[256][256];
+ uint8_t thefilterb[256][256];
+ uint16_t purpleline[256][3];
+
+ texture_t texture_cache[2][TEX_CACHE_MAX];
+ uint8_t texture_present[2][16384];
+ int texture_last_removed;
+
+ uint32_t palette_checksum[2];
+ int palette_dirty[2];
+
+ uint64_t time;
+ int render_time[4];
+
+ int use_recompiler;
+ void *codegen_data;
+
+ struct voodoo_set_t *set;
+
+
+ uint8_t *vram, *changedvram;
+
+ void *p;
+} voodoo_t;
+
+typedef struct voodoo_set_t
+{
+ voodoo_t *voodoos[2];
+
+ mem_mapping_t snoop_mapping;
+
+ int nr_cards;
+} voodoo_set_t;
+
+
+extern rgba8_t rgb332[0x100], ai44[0x100], rgb565[0x10000], argb1555[0x10000], argb4444[0x10000], ai88[0x10000];
+
+
+void voodoo_generate_vb_filters(voodoo_t *voodoo, int fcr, int fcg);
+
+void voodoo_recalc(voodoo_t *voodoo);
+void voodoo_update_ncc(voodoo_t *voodoo, int tmu);
+
+void *voodoo_2d3d_card_init(int type);
+void voodoo_card_close(voodoo_t *voodoo);
diff --git a/src/vid_voodoo_display.c b/src/vid_voodoo_display.c
new file mode 100644
index 0000000..9ce92dd
--- /dev/null
+++ b/src/vid_voodoo_display.c
@@ -0,0 +1,609 @@
+#include "ibm.h"
+#include "device.h"
+#include "mem.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_svga.h"
+#include "vid_voodoo.h"
+#include "vid_voodoo_common.h"
+#include "vid_voodoo_display.h"
+#include "vid_voodoo_regs.h"
+#include "vid_voodoo_render.h"
+
+void voodoo_update_ncc(voodoo_t *voodoo, int tmu)
+{
+ int tbl;
+
+ for (tbl = 0; tbl < 2; tbl++)
+ {
+ int col;
+
+ for (col = 0; col < 256; col++)
+ {
+ int y = (col >> 4), i = (col >> 2) & 3, q = col & 3;
+ int i_r, i_g, i_b;
+ int q_r, q_g, q_b;
+
+ y = (voodoo->nccTable[tmu][tbl].y[y >> 2] >> ((y & 3) * 8)) & 0xff;
+
+ i_r = (voodoo->nccTable[tmu][tbl].i[i] >> 18) & 0x1ff;
+ if (i_r & 0x100)
+ i_r |= 0xfffffe00;
+ i_g = (voodoo->nccTable[tmu][tbl].i[i] >> 9) & 0x1ff;
+ if (i_g & 0x100)
+ i_g |= 0xfffffe00;
+ i_b = voodoo->nccTable[tmu][tbl].i[i] & 0x1ff;
+ if (i_b & 0x100)
+ i_b |= 0xfffffe00;
+
+ q_r = (voodoo->nccTable[tmu][tbl].q[q] >> 18) & 0x1ff;
+ if (q_r & 0x100)
+ q_r |= 0xfffffe00;
+ q_g = (voodoo->nccTable[tmu][tbl].q[q] >> 9) & 0x1ff;
+ if (q_g & 0x100)
+ q_g |= 0xfffffe00;
+ q_b = voodoo->nccTable[tmu][tbl].q[q] & 0x1ff;
+ if (q_b & 0x100)
+ q_b |= 0xfffffe00;
+
+ voodoo->ncc_lookup[tmu][tbl][col].rgba.r = CLAMP(y + i_r + q_r);
+ voodoo->ncc_lookup[tmu][tbl][col].rgba.g = CLAMP(y + i_g + q_g);
+ voodoo->ncc_lookup[tmu][tbl][col].rgba.b = CLAMP(y + i_b + q_b);
+ voodoo->ncc_lookup[tmu][tbl][col].rgba.a = 0xff;
+ }
+ }
+}
+
+void voodoo_pixelclock_update(voodoo_t *voodoo)
+{
+ int m = (voodoo->dac_pll_regs[0] & 0x7f) + 2;
+ int n1 = ((voodoo->dac_pll_regs[0] >> 8) & 0x1f) + 2;
+ int n2 = ((voodoo->dac_pll_regs[0] >> 13) & 0x07);
+ float t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2);
+ double clock_const;
+ int line_length;
+
+ if ((voodoo->dac_data[6] & 0xf0) == 0x20 ||
+ (voodoo->dac_data[6] & 0xf0) == 0x60 ||
+ (voodoo->dac_data[6] & 0xf0) == 0x70)
+ t /= 2.0f;
+
+ line_length = (voodoo->hSync & 0xff) + ((voodoo->hSync >> 16) & 0x3ff);
+
+// pclog("Pixel clock %f MHz hsync %08x line_length %d\n", t, voodoo->hSync, line_length);
+
+ voodoo->pixel_clock = t;
+
+ clock_const = cpuclock / t;
+ voodoo->line_time = (uint64_t)((double)line_length * clock_const * (double)(1ull << 32));
+}
+
+static void voodoo_calc_clutData(voodoo_t *voodoo)
+{
+ int c;
+
+ for (c = 0; c < 256; c++)
+ {
+ voodoo->clutData256[c].r = (voodoo->clutData[c >> 3].r*(8-(c & 7)) +
+ voodoo->clutData[(c >> 3)+1].r*(c & 7)) >> 3;
+ voodoo->clutData256[c].g = (voodoo->clutData[c >> 3].g*(8-(c & 7)) +
+ voodoo->clutData[(c >> 3)+1].g*(c & 7)) >> 3;
+ voodoo->clutData256[c].b = (voodoo->clutData[c >> 3].b*(8-(c & 7)) +
+ voodoo->clutData[(c >> 3)+1].b*(c & 7)) >> 3;
+ }
+
+ for (c = 0; c < 65536; c++)
+ {
+ int r = (c >> 8) & 0xf8;
+ int g = (c >> 3) & 0xfc;
+ int b = (c << 3) & 0xf8;
+// r |= (r >> 5);
+// g |= (g >> 6);
+// b |= (b >> 5);
+
+ voodoo->video_16to32[c] = (voodoo->clutData256[r].r << 16) | (voodoo->clutData256[g].g << 8) | voodoo->clutData256[b].b;
+ }
+}
+
+
+
+#define FILTDIV 256
+
+static int FILTCAP, FILTCAPG, FILTCAPB = 0; /* color filter threshold values */
+
+void voodoo_generate_filter_v1(voodoo_t *voodoo)
+{
+ int g, h;
+ float difference, diffg, diffb;
+ float thiscol, thiscolg, thiscolb, lined;
+ float fcr, fcg, fcb;
+
+ fcr = FILTCAP * 5;
+ fcg = FILTCAPG * 6;
+ fcb = FILTCAPB * 5;
+
+ for (g=0;g FILTCAP)
+ difference = FILTCAP;
+ if (difference < -FILTCAP)
+ difference = -FILTCAP;
+
+ if (diffg > FILTCAPG)
+ diffg = FILTCAPG;
+ if (diffg < -FILTCAPG)
+ diffg = -FILTCAPG;
+
+ if (diffb > FILTCAPB)
+ diffb = FILTCAPB;
+ if (diffb < -FILTCAPB)
+ diffb = -FILTCAPB;
+
+ // hack - to make it not bleed onto black
+ //if (g == 0){
+ //difference = diffg = diffb = 0;
+ //}
+
+ if ((difference < fcr) || (-difference > -fcr))
+ thiscol = g + (difference / 2);
+ if ((diffg < fcg) || (-diffg > -fcg))
+ thiscolg = g + (diffg / 2); /* need these divides so we can actually undither! */
+ if ((diffb < fcb) || (-diffb > -fcb))
+ thiscolb = g + (diffb / 2);
+
+ if (thiscol < 0)
+ thiscol = 0;
+ if (thiscol > FILTDIV-1)
+ thiscol = FILTDIV-1;
+
+ if (thiscolg < 0)
+ thiscolg = 0;
+ if (thiscolg > FILTDIV-1)
+ thiscolg = FILTDIV-1;
+
+ if (thiscolb < 0)
+ thiscolb = 0;
+ if (thiscolb > FILTDIV-1)
+ thiscolb = FILTDIV-1;
+
+ voodoo->thefilter[g][h] = thiscol;
+ voodoo->thefilterg[g][h] = thiscolg;
+ voodoo->thefilterb[g][h] = thiscolb;
+ }
+
+ lined = g + 4;
+ if (lined > 255)
+ lined = 255;
+ voodoo->purpleline[g][0] = lined;
+ voodoo->purpleline[g][2] = lined;
+
+ lined = g + 0;
+ if (lined > 255)
+ lined = 255;
+ voodoo->purpleline[g][1] = lined;
+ }
+}
+
+void voodoo_generate_filter_v2(voodoo_t *voodoo)
+{
+ int g, h;
+ float difference;
+ float thiscol, thiscolg, thiscolb;
+ float clr, clg, clb = 0;
+ float fcr, fcg, fcb = 0;
+
+ // pre-clamping
+
+ fcr = FILTCAP;
+ fcg = FILTCAPG;
+ fcb = FILTCAPB;
+
+ if (fcr > 32) fcr = 32;
+ if (fcg > 32) fcg = 32;
+ if (fcb > 32) fcb = 32;
+
+ for (g=0;g<256;g++) // pixel 1 - our target pixel we want to bleed into
+ {
+ for (h=0;h<256;h++) // pixel 2 - our main pixel
+ {
+ float avg;
+ float avgdiff;
+
+ difference = (float)(g - h);
+ avg = (float)((g + g + g + g + h) / 5);
+ avgdiff = avg - (float)((g + h + h + h + h) / 5);
+ if (avgdiff < 0) avgdiff *= -1;
+ if (difference < 0) difference *= -1;
+
+ thiscol = thiscolg = thiscolb = g;
+
+ // try lighten
+ if (h > g)
+ {
+ clr = clg = clb = avgdiff;
+
+ if (clr>fcr) clr=fcr;
+ if (clg>fcg) clg=fcg;
+ if (clb>fcb) clb=fcb;
+
+
+ thiscol = g + clr;
+ thiscolg = g + clg;
+ thiscolb = g + clb;
+
+ if (thiscol>g+FILTCAP)
+ thiscol=g+FILTCAP;
+ if (thiscolg>g+FILTCAPG)
+ thiscolg=g+FILTCAPG;
+ if (thiscolb>g+FILTCAPB)
+ thiscolb=g+FILTCAPB;
+
+
+ if (thiscol>g+avgdiff)
+ thiscol=g+avgdiff;
+ if (thiscolg>g+avgdiff)
+ thiscolg=g+avgdiff;
+ if (thiscolb>g+avgdiff)
+ thiscolb=g+avgdiff;
+
+ }
+
+ if (difference > FILTCAP)
+ thiscol = g;
+ if (difference > FILTCAPG)
+ thiscolg = g;
+ if (difference > FILTCAPB)
+ thiscolb = g;
+
+ // clamp
+ if (thiscol < 0) thiscol = 0;
+ if (thiscolg < 0) thiscolg = 0;
+ if (thiscolb < 0) thiscolb = 0;
+
+ if (thiscol > 255) thiscol = 255;
+ if (thiscolg > 255) thiscolg = 255;
+ if (thiscolb > 255) thiscolb = 255;
+
+ // add to the table
+ voodoo->thefilter[g][h] = (thiscol);
+ voodoo->thefilterg[g][h] = (thiscolg);
+ voodoo->thefilterb[g][h] = (thiscolb);
+
+ // debug the ones that don't give us much of a difference
+ //if (difference < FILTCAP)
+ //pclog("Voodoofilter: %ix%i - %f difference, %f average difference, R=%f, G=%f, B=%f\n", g, h, difference, avgdiff, thiscol, thiscolg, thiscolb);
+ }
+
+ }
+}
+
+void voodoo_threshold_check(voodoo_t *voodoo)
+{
+ int r, g, b;
+
+ if (!voodoo->scrfilterEnabled)
+ return; /* considered disabled; don't check and generate */
+
+ /* Check for changes, to generate anew table */
+ if (voodoo->scrfilterThreshold != voodoo->scrfilterThresholdOld)
+ {
+ r = (voodoo->scrfilterThreshold >> 16) & 0xFF;
+ g = (voodoo->scrfilterThreshold >> 8 ) & 0xFF;
+ b = voodoo->scrfilterThreshold & 0xFF;
+
+ FILTCAP = r;
+ FILTCAPG = g;
+ FILTCAPB = b;
+
+ pclog("Voodoo Filter Threshold Check: %06x - RED %i GREEN %i BLUE %i\n", voodoo->scrfilterThreshold, r, g, b);
+
+ voodoo->scrfilterThresholdOld = voodoo->scrfilterThreshold;
+
+ if (voodoo->type == VOODOO_2)
+ voodoo_generate_filter_v2(voodoo);
+ else
+ voodoo_generate_filter_v1(voodoo);
+
+ if (voodoo->type >= VOODOO_BANSHEE)
+ voodoo_generate_vb_filters(voodoo, FILTCAP, FILTCAPG);
+ }
+}
+
+static void voodoo_filterline_v1(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line)
+{
+ int x;
+
+ // Scratchpad for avoiding feedback streaks
+ uint8_t fil3[(voodoo->h_disp) * 3];
+
+ /* 16 to 32-bit */
+ for (x=0; x> 5) & 63) << 2);
+ fil[x*3+2] = (((src[x] >> 11) & 31) << 3);
+
+ // Copy to our scratchpads
+ fil3[x*3+0] = fil[x*3+0];
+ fil3[x*3+1] = fil[x*3+1];
+ fil3[x*3+2] = fil[x*3+2];
+ }
+
+
+ /* lines */
+
+ if (line & 1)
+ {
+ for (x=0; xpurpleline[fil[x*3]][0];
+ fil[x*3+1] = voodoo->purpleline[fil[x*3+1]][1];
+ fil[x*3+2] = voodoo->purpleline[fil[x*3+2]][2];
+ }
+ }
+
+
+ /* filtering time */
+
+ for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]];
+ fil3[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]];
+ fil3[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]];
+ }
+
+ for (x=1; xthefilterb[fil3[x*3]][fil3[ (x-1) *3]];
+ fil[(x)*3+1] = voodoo->thefilterg[fil3[x*3+1]][fil3[ (x-1) *3+1]];
+ fil[(x)*3+2] = voodoo->thefilter[fil3[x*3+2]][fil3[ (x-1) *3+2]];
+ }
+
+ for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]];
+ fil3[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]];
+ fil3[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]];
+ }
+
+ for (x=0; xthefilterb[fil3[x*3]][fil3[ (x+1) *3]];
+ fil[(x)*3+1] = voodoo->thefilterg[fil3[x*3+1]][fil3[ (x+1) *3+1]];
+ fil[(x)*3+2] = voodoo->thefilter[fil3[x*3+2]][fil3[ (x+1) *3+2]];
+ }
+}
+
+
+static void voodoo_filterline_v2(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line)
+{
+ int x;
+
+ // Scratchpad for blending filter
+ uint8_t fil3[(voodoo->h_disp) * 3];
+
+ /* 16 to 32-bit */
+ for (x=0; x> 5) & 63) << 2);
+ fil3[x*3+2] = fil[x*3+2] = (((src[x] >> 11) & 31) << 3);
+ }
+
+ /* filtering time */
+
+ for (x=1; xthefilterb [((src[x+3] & 31) << 3)] [((src[x] & 31) << 3)];
+ fil3[(x+3)*3+1] = voodoo->thefilterg [(((src[x+3] >> 5) & 63) << 2)] [(((src[x] >> 5) & 63) << 2)];
+ fil3[(x+3)*3+2] = voodoo->thefilter [(((src[x+3] >> 11) & 31) << 3)] [(((src[x] >> 11) & 31) << 3)];
+
+ fil[(x+2)*3] = voodoo->thefilterb [fil3[(x+2)*3]][((src[x] & 31) << 3)];
+ fil[(x+2)*3+1] = voodoo->thefilterg [fil3[(x+2)*3+1]][(((src[x] >> 5) & 63) << 2)];
+ fil[(x+2)*3+2] = voodoo->thefilter [fil3[(x+2)*3+2]][(((src[x] >> 11) & 31) << 3)];
+
+ fil3[(x+1)*3] = voodoo->thefilterb [fil[(x+1)*3]][((src[x] & 31) << 3)];
+ fil3[(x+1)*3+1] = voodoo->thefilterg [fil[(x+1)*3+1]][(((src[x] >> 5) & 63) << 2)];
+ fil3[(x+1)*3+2] = voodoo->thefilter [fil[(x+1)*3+2]][(((src[x] >> 11) & 31) << 3)];
+
+ fil[(x-1)*3] = voodoo->thefilterb [fil3[(x-1)*3]][((src[x] & 31) << 3)];
+ fil[(x-1)*3+1] = voodoo->thefilterg [fil3[(x-1)*3+1]][(((src[x] >> 5) & 63) << 2)];
+ fil[(x-1)*3+2] = voodoo->thefilter [fil3[(x-1)*3+2]][(((src[x] >> 11) & 31) << 3)];
+ }
+
+ // unroll for edge cases
+
+ fil3[(column-3)*3] = voodoo->thefilterb [((src[column-3] & 31) << 3)] [((src[column] & 31) << 3)];
+ fil3[(column-3)*3+1] = voodoo->thefilterg [(((src[column-3] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)];
+ fil3[(column-3)*3+2] = voodoo->thefilter [(((src[column-3] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)];
+
+ fil3[(column-2)*3] = voodoo->thefilterb [((src[column-2] & 31) << 3)] [((src[column] & 31) << 3)];
+ fil3[(column-2)*3+1] = voodoo->thefilterg [(((src[column-2] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)];
+ fil3[(column-2)*3+2] = voodoo->thefilter [(((src[column-2] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)];
+
+ fil3[(column-1)*3] = voodoo->thefilterb [((src[column-1] & 31) << 3)] [((src[column] & 31) << 3)];
+ fil3[(column-1)*3+1] = voodoo->thefilterg [(((src[column-1] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)];
+ fil3[(column-1)*3+2] = voodoo->thefilter [(((src[column-1] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)];
+
+ fil[(column-2)*3] = voodoo->thefilterb [fil3[(column-2)*3]][((src[column] & 31) << 3)];
+ fil[(column-2)*3+1] = voodoo->thefilterg [fil3[(column-2)*3+1]][(((src[column] >> 5) & 63) << 2)];
+ fil[(column-2)*3+2] = voodoo->thefilter [fil3[(column-2)*3+2]][(((src[column] >> 11) & 31) << 3)];
+
+ fil[(column-1)*3] = voodoo->thefilterb [fil3[(column-1)*3]][((src[column] & 31) << 3)];
+ fil[(column-1)*3+1] = voodoo->thefilterg [fil3[(column-1)*3+1]][(((src[column] >> 5) & 63) << 2)];
+ fil[(column-1)*3+2] = voodoo->thefilter [fil3[(column-1)*3+2]][(((src[column] >> 11) & 31) << 3)];
+
+ fil3[(column-1)*3] = voodoo->thefilterb [fil[(column-1)*3]][((src[column] & 31) << 3)];
+ fil3[(column-1)*3+1] = voodoo->thefilterg [fil[(column-1)*3+1]][(((src[column] >> 5) & 63) << 2)];
+ fil3[(column-1)*3+2] = voodoo->thefilter [fil[(column-1)*3+2]][(((src[column] >> 11) & 31) << 3)];
+}
+
+void voodoo_callback(void *p)
+{
+ voodoo_t *voodoo = (voodoo_t *)p;
+
+ if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS)
+ {
+ if (voodoo->line < voodoo->v_disp)
+ {
+ voodoo_t *draw_voodoo;
+ int draw_line;
+
+ if (SLI_ENABLED)
+ {
+ if (voodoo == voodoo->set->voodoos[1])
+ goto skip_draw;
+
+ if (((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) ? 1 : 0) == (voodoo->line & 1))
+ draw_voodoo = voodoo;
+ else
+ draw_voodoo = voodoo->set->voodoos[1];
+ draw_line = voodoo->line >> 1;
+ }
+ else
+ {
+ if (!(voodoo->fbiInit0 & 1))
+ goto skip_draw;
+ draw_voodoo = voodoo;
+ draw_line = voodoo->line;
+ }
+
+ if (draw_voodoo->dirty_line[draw_line])
+ {
+ uint32_t *p = &((uint32_t *)buffer32->line[voodoo->line])[32];
+ uint16_t *src = (uint16_t *)&draw_voodoo->fb_mem[draw_voodoo->front_offset + draw_line*draw_voodoo->row_width];
+ int x;
+
+ draw_voodoo->dirty_line[draw_line] = 0;
+
+ if (voodoo->line < voodoo->dirty_line_low)
+ {
+ voodoo->dirty_line_low = voodoo->line;
+ video_wait_for_buffer();
+ }
+ if (voodoo->line > voodoo->dirty_line_high)
+ voodoo->dirty_line_high = voodoo->line;
+
+ if (voodoo->scrfilter && voodoo->scrfilterEnabled)
+ {
+ uint8_t fil[(voodoo->h_disp) * 3]; /* interleaved 24-bit RGB */
+
+ if (voodoo->type == VOODOO_2)
+ voodoo_filterline_v2(voodoo, fil, voodoo->h_disp, src, voodoo->line);
+ else
+ voodoo_filterline_v1(voodoo, fil, voodoo->h_disp, src, voodoo->line);
+
+ for (x = 0; x < voodoo->h_disp; x++)
+ {
+ p[x] = (voodoo->clutData256[fil[x*3]].b << 0 | voodoo->clutData256[fil[x*3+1]].g << 8 | voodoo->clutData256[fil[x*3+2]].r << 16);
+ }
+ }
+ else
+ {
+ for (x = 0; x < voodoo->h_disp; x++)
+ {
+ p[x] = draw_voodoo->video_16to32[src[x]];
+ }
+ }
+ }
+ }
+ }
+skip_draw:
+ if (voodoo->line == voodoo->v_disp)
+ {
+// pclog("retrace %i %i %08x %i\n", voodoo->retrace_count, voodoo->swap_interval, voodoo->swap_offset, voodoo->swap_pending);
+ voodoo->retrace_count++;
+ if (SLI_ENABLED && (voodoo->fbiInit2 & FBIINIT2_SWAP_ALGORITHM_MASK) == FBIINIT2_SWAP_ALGORITHM_SLI_SYNC)
+ {
+ if (voodoo == voodoo->set->voodoos[0])
+ {
+ voodoo_t *voodoo_1 = voodoo->set->voodoos[1];
+
+ thread_lock_mutex(voodoo->swap_mutex);
+ /*Only swap if both Voodoos are waiting for buffer swap*/
+ if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval) &&
+ voodoo_1->swap_pending && (voodoo_1->retrace_count > voodoo_1->swap_interval))
+ {
+ memset(voodoo->dirty_line, 1, 1024);
+ voodoo->retrace_count = 0;
+ voodoo->front_offset = voodoo->swap_offset;
+ if (voodoo->swap_count > 0)
+ voodoo->swap_count--;
+ voodoo->swap_pending = 0;
+
+ memset(voodoo_1->dirty_line, 1, 1024);
+ voodoo_1->retrace_count = 0;
+ voodoo_1->front_offset = voodoo_1->swap_offset;
+ if (voodoo_1->swap_count > 0)
+ voodoo_1->swap_count--;
+ voodoo_1->swap_pending = 0;
+ thread_unlock_mutex(voodoo->swap_mutex);
+
+ thread_set_event(voodoo->wake_fifo_thread);
+ thread_set_event(voodoo_1->wake_fifo_thread);
+
+ voodoo->frame_count++;
+ voodoo_1->frame_count++;
+ }
+ else
+ thread_unlock_mutex(voodoo->swap_mutex);
+ }
+ }
+ else
+ {
+ thread_lock_mutex(voodoo->swap_mutex);
+ if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval))
+ {
+ voodoo->front_offset = voodoo->swap_offset;
+ if (voodoo->swap_count > 0)
+ voodoo->swap_count--;
+ voodoo->swap_pending = 0;
+ thread_unlock_mutex(voodoo->swap_mutex);
+
+ memset(voodoo->dirty_line, 1, 1024);
+ voodoo->retrace_count = 0;
+ thread_set_event(voodoo->wake_fifo_thread);
+ voodoo->frame_count++;
+ }
+ else
+ thread_unlock_mutex(voodoo->swap_mutex);
+ }
+ voodoo->v_retrace = 1;
+ }
+ voodoo->line++;
+
+ if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS)
+ {
+ if (voodoo->line == voodoo->v_disp)
+ {
+ if (voodoo->dirty_line_high > voodoo->dirty_line_low)
+ svga_doblit(0, voodoo->v_disp, voodoo->h_disp, voodoo->v_disp-1, voodoo->svga);
+ if (voodoo->clutData_dirty)
+ {
+ voodoo->clutData_dirty = 0;
+ voodoo_calc_clutData(voodoo);
+ }
+ voodoo->dirty_line_high = -1;
+ voodoo->dirty_line_low = 2000;
+ }
+ }
+
+ if (voodoo->line >= voodoo->v_total)
+ {
+ voodoo->line = 0;
+ voodoo->v_retrace = 0;
+ }
+ if (voodoo->line_time)
+ timer_advance_u64(&voodoo->timer, voodoo->line_time);
+ else
+ timer_advance_u64(&voodoo->timer, TIMER_USEC * 32);
+}
diff --git a/src/vid_voodoo_display.h b/src/vid_voodoo_display.h
new file mode 100644
index 0000000..46cbc00
--- /dev/null
+++ b/src/vid_voodoo_display.h
@@ -0,0 +1,6 @@
+void voodoo_update_ncc(voodoo_t *voodoo, int tmu);
+void voodoo_pixelclock_update(voodoo_t *voodoo);
+void voodoo_generate_filter_v1(voodoo_t *voodoo);
+void voodoo_generate_filter_v2(voodoo_t *voodoo);
+void voodoo_threshold_check(voodoo_t *voodoo);
+void voodoo_callback(void *p);
diff --git a/src/vid_voodoo_dither.h b/src/vid_voodoo_dither.h
index 7ec7471..c1109c9 100644
--- a/src/vid_voodoo_dither.h
+++ b/src/vid_voodoo_dither.h
@@ -1,4 +1,4 @@
-uint8_t dither_rb[256][4][4] =
+static const uint8_t dither_rb[256][4][4] =
{
{
{0, 0, 0, 0},
@@ -1538,7 +1538,7 @@ uint8_t dither_rb[256][4][4] =
},
};
-uint8_t dither_g[256][4][4] =
+static const uint8_t dither_g[256][4][4] =
{
{
{0, 0, 0, 0},
@@ -3078,7 +3078,7 @@ uint8_t dither_g[256][4][4] =
},
};
-uint8_t dither_rb2x2[256][2][2] =
+static const uint8_t dither_rb2x2[256][2][2] =
{
{
{0, 0},
@@ -4106,7 +4106,7 @@ uint8_t dither_rb2x2[256][2][2] =
},
};
-uint8_t dither_g2x2[256][2][2] =
+static const uint8_t dither_g2x2[256][2][2] =
{
{
{0, 0},
@@ -5134,3 +5134,5147 @@ uint8_t dither_g2x2[256][2][2] =
},
};
+
+
+/* Dither subtraction */
+
+static const uint8_t dithersub_rb[256][4][4] =
+{
+ {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {9, 5, 8, 4},
+ {3, 7, 2, 6},
+ {7, 3, 8, 4},
+ {1, 5, 2, 6},
+ },
+ {
+ {10, 6, 9, 5},
+ {4, 8, 3, 7},
+ {8, 4, 9, 5},
+ {2, 6, 3, 7},
+ },
+ {
+ {11, 7, 10, 6},
+ {5, 9, 4, 8},
+ {9, 5, 10, 6},
+ {3, 7, 4, 8},
+ },
+ {
+ {12, 8, 11, 7},
+ {6, 10, 5, 9},
+ {10, 6, 11, 7},
+ {4, 8, 5, 9},
+ },
+ {
+ {13, 9, 12, 8},
+ {7, 11, 6, 10},
+ {11, 7, 12, 8},
+ {5, 9, 6, 10},
+ },
+ {
+ {14, 10, 13, 9},
+ {8, 12, 7, 11},
+ {12, 8, 13, 9},
+ {6, 10, 7, 11},
+ },
+ {
+ {15, 11, 14, 10},
+ {9, 13, 8, 12},
+ {13, 9, 14, 10},
+ {7, 11, 8, 12},
+ },
+ {
+ {16, 12, 15, 11},
+ {10, 14, 9, 13},
+ {14, 10, 15, 11},
+ {8, 12, 9, 13},
+ },
+ {
+ {17, 13, 16, 12},
+ {11, 15, 10, 14},
+ {15, 11, 16, 12},
+ {9, 13, 10, 14},
+ },
+ {
+ {18, 14, 17, 13},
+ {12, 16, 11, 15},
+ {16, 12, 17, 13},
+ {10, 14, 11, 15},
+ },
+ {
+ {19, 15, 18, 14},
+ {13, 17, 12, 16},
+ {17, 13, 18, 14},
+ {11, 15, 12, 16},
+ },
+ {
+ {20, 16, 19, 15},
+ {14, 18, 13, 17},
+ {18, 14, 19, 15},
+ {12, 16, 13, 17},
+ },
+ {
+ {21, 17, 20, 16},
+ {15, 19, 14, 18},
+ {19, 15, 20, 16},
+ {13, 17, 14, 18},
+ },
+ {
+ {22, 18, 21, 17},
+ {16, 20, 15, 19},
+ {20, 16, 21, 17},
+ {14, 18, 15, 19},
+ },
+ {
+ {23, 19, 22, 18},
+ {17, 21, 16, 20},
+ {21, 17, 22, 18},
+ {15, 19, 16, 20},
+ },
+ {
+ {24, 20, 23, 19},
+ {18, 22, 17, 21},
+ {22, 18, 23, 19},
+ {16, 20, 17, 21},
+ },
+ {
+ {25, 21, 24, 20},
+ {19, 23, 18, 22},
+ {23, 19, 24, 20},
+ {17, 21, 18, 22},
+ },
+ {
+ {26, 22, 25, 21},
+ {20, 24, 19, 23},
+ {24, 20, 25, 21},
+ {18, 22, 19, 23},
+ },
+ {
+ {27, 23, 26, 22},
+ {21, 25, 20, 24},
+ {25, 21, 26, 22},
+ {19, 23, 20, 24},
+ },
+ {
+ {28, 24, 27, 23},
+ {22, 26, 21, 25},
+ {26, 22, 27, 23},
+ {20, 24, 21, 25},
+ },
+ {
+ {29, 25, 28, 24},
+ {23, 27, 22, 26},
+ {27, 23, 28, 24},
+ {21, 25, 22, 26},
+ },
+ {
+ {30, 26, 29, 25},
+ {24, 28, 23, 27},
+ {28, 24, 29, 25},
+ {22, 26, 23, 27},
+ },
+ {
+ {31, 27, 30, 26},
+ {25, 29, 24, 28},
+ {29, 25, 30, 26},
+ {23, 27, 24, 28},
+ },
+ {
+ {32, 28, 31, 27},
+ {26, 30, 25, 29},
+ {30, 26, 31, 27},
+ {24, 28, 25, 29},
+ },
+ {
+ {33, 29, 32, 28},
+ {27, 31, 26, 30},
+ {31, 27, 32, 28},
+ {25, 29, 26, 30},
+ },
+ {
+ {34, 30, 33, 29},
+ {28, 32, 27, 31},
+ {32, 28, 33, 29},
+ {26, 30, 27, 31},
+ },
+ {
+ {35, 31, 34, 30},
+ {29, 33, 28, 32},
+ {33, 29, 34, 30},
+ {27, 31, 28, 32},
+ },
+ {
+ {36, 32, 35, 31},
+ {30, 34, 29, 33},
+ {34, 30, 35, 31},
+ {28, 32, 29, 33},
+ },
+ {
+ {37, 33, 36, 32},
+ {31, 35, 30, 34},
+ {35, 31, 36, 32},
+ {29, 33, 30, 34},
+ },
+ {
+ {38, 34, 37, 33},
+ {32, 36, 31, 35},
+ {36, 32, 37, 33},
+ {30, 34, 31, 35},
+ },
+ {
+ {39, 35, 38, 34},
+ {33, 37, 32, 36},
+ {37, 33, 38, 34},
+ {31, 35, 32, 36},
+ },
+ {
+ {40, 36, 39, 35},
+ {34, 38, 33, 37},
+ {38, 34, 39, 35},
+ {32, 36, 33, 37},
+ },
+ {
+ {41, 37, 40, 36},
+ {35, 39, 34, 38},
+ {39, 35, 40, 36},
+ {33, 37, 34, 38},
+ },
+ {
+ {42, 38, 41, 37},
+ {36, 40, 35, 39},
+ {40, 36, 41, 37},
+ {34, 38, 35, 39},
+ },
+ {
+ {43, 39, 42, 38},
+ {37, 41, 36, 40},
+ {41, 37, 42, 38},
+ {35, 39, 36, 40},
+ },
+ {
+ {44, 40, 43, 39},
+ {38, 42, 37, 41},
+ {42, 38, 43, 39},
+ {36, 40, 37, 41},
+ },
+ {
+ {45, 41, 44, 40},
+ {39, 43, 38, 42},
+ {43, 39, 44, 40},
+ {37, 41, 38, 42},
+ },
+ {
+ {46, 42, 45, 41},
+ {40, 44, 39, 43},
+ {44, 40, 45, 41},
+ {38, 42, 39, 43},
+ },
+ {
+ {47, 43, 46, 42},
+ {41, 45, 40, 44},
+ {45, 41, 46, 42},
+ {39, 43, 40, 44},
+ },
+ {
+ {48, 44, 47, 43},
+ {42, 46, 41, 45},
+ {46, 42, 47, 43},
+ {40, 44, 41, 45},
+ },
+ {
+ {49, 45, 48, 44},
+ {43, 47, 42, 46},
+ {47, 43, 48, 44},
+ {41, 45, 42, 46},
+ },
+ {
+ {50, 46, 49, 45},
+ {44, 48, 43, 47},
+ {48, 44, 49, 45},
+ {42, 46, 43, 47},
+ },
+ {
+ {51, 47, 50, 46},
+ {45, 49, 44, 48},
+ {49, 45, 50, 46},
+ {43, 47, 44, 48},
+ },
+ {
+ {52, 48, 51, 47},
+ {46, 50, 45, 49},
+ {50, 46, 51, 47},
+ {44, 48, 45, 49},
+ },
+ {
+ {53, 49, 52, 48},
+ {47, 51, 46, 50},
+ {51, 47, 52, 48},
+ {45, 49, 46, 50},
+ },
+ {
+ {54, 50, 53, 49},
+ {48, 52, 47, 51},
+ {52, 48, 53, 49},
+ {46, 50, 47, 51},
+ },
+ {
+ {55, 51, 54, 50},
+ {49, 53, 48, 52},
+ {53, 49, 54, 50},
+ {47, 51, 48, 52},
+ },
+ {
+ {56, 52, 55, 51},
+ {50, 54, 49, 53},
+ {54, 50, 55, 51},
+ {48, 52, 49, 53},
+ },
+ {
+ {57, 53, 56, 52},
+ {51, 55, 50, 54},
+ {55, 51, 56, 52},
+ {49, 53, 50, 54},
+ },
+ {
+ {58, 54, 57, 53},
+ {52, 56, 51, 55},
+ {56, 52, 57, 53},
+ {50, 54, 51, 55},
+ },
+ {
+ {59, 55, 58, 54},
+ {53, 57, 52, 56},
+ {57, 53, 58, 54},
+ {51, 55, 52, 56},
+ },
+ {
+ {60, 56, 59, 55},
+ {54, 58, 53, 57},
+ {58, 54, 59, 55},
+ {52, 56, 53, 57},
+ },
+ {
+ {61, 57, 60, 56},
+ {55, 59, 54, 58},
+ {59, 55, 60, 56},
+ {53, 57, 54, 58},
+ },
+ {
+ {62, 58, 61, 57},
+ {56, 60, 55, 59},
+ {60, 56, 61, 57},
+ {54, 58, 55, 59},
+ },
+ {
+ {63, 59, 62, 58},
+ {57, 61, 56, 60},
+ {61, 57, 62, 58},
+ {55, 59, 56, 60},
+ },
+ {
+ {64, 60, 63, 59},
+ {58, 62, 57, 61},
+ {62, 58, 63, 59},
+ {56, 60, 57, 61},
+ },
+ {
+ {65, 61, 64, 60},
+ {59, 63, 58, 62},
+ {63, 59, 64, 60},
+ {57, 61, 58, 62},
+ },
+ {
+ {66, 62, 65, 61},
+ {60, 64, 59, 63},
+ {64, 60, 65, 61},
+ {58, 62, 59, 63},
+ },
+ {
+ {67, 63, 66, 62},
+ {61, 65, 60, 64},
+ {65, 61, 66, 62},
+ {59, 63, 60, 64},
+ },
+ {
+ {68, 64, 67, 63},
+ {62, 66, 61, 65},
+ {66, 62, 67, 63},
+ {60, 64, 61, 65},
+ },
+ {
+ {69, 65, 68, 64},
+ {63, 67, 62, 66},
+ {67, 63, 68, 64},
+ {61, 65, 62, 66},
+ },
+ {
+ {70, 66, 69, 65},
+ {64, 68, 63, 67},
+ {68, 64, 69, 65},
+ {62, 66, 63, 67},
+ },
+ {
+ {71, 67, 70, 66},
+ {65, 69, 64, 68},
+ {69, 65, 70, 66},
+ {63, 67, 64, 68},
+ },
+ {
+ {72, 68, 71, 67},
+ {66, 70, 65, 69},
+ {70, 66, 71, 67},
+ {64, 68, 65, 69},
+ },
+ {
+ {73, 69, 72, 68},
+ {67, 71, 66, 70},
+ {71, 67, 72, 68},
+ {65, 69, 66, 70},
+ },
+ {
+ {74, 70, 73, 69},
+ {68, 72, 67, 71},
+ {72, 68, 73, 69},
+ {66, 70, 67, 71},
+ },
+ {
+ {75, 71, 74, 70},
+ {69, 73, 68, 72},
+ {73, 69, 74, 70},
+ {67, 71, 68, 72},
+ },
+ {
+ {76, 72, 75, 71},
+ {70, 74, 69, 73},
+ {74, 70, 75, 71},
+ {68, 72, 69, 73},
+ },
+ {
+ {77, 73, 76, 72},
+ {71, 75, 70, 74},
+ {75, 71, 76, 72},
+ {69, 73, 70, 74},
+ },
+ {
+ {78, 74, 77, 73},
+ {72, 76, 71, 75},
+ {76, 72, 77, 73},
+ {70, 74, 71, 75},
+ },
+ {
+ {79, 75, 78, 74},
+ {73, 77, 72, 76},
+ {77, 73, 78, 74},
+ {71, 75, 72, 76},
+ },
+ {
+ {80, 76, 79, 75},
+ {74, 78, 73, 77},
+ {78, 74, 79, 75},
+ {72, 76, 73, 77},
+ },
+ {
+ {81, 77, 80, 76},
+ {75, 79, 74, 78},
+ {79, 75, 80, 76},
+ {73, 77, 74, 78},
+ },
+ {
+ {82, 78, 81, 77},
+ {76, 80, 75, 79},
+ {80, 76, 81, 77},
+ {74, 78, 75, 79},
+ },
+ {
+ {83, 79, 82, 78},
+ {77, 81, 76, 80},
+ {81, 77, 82, 78},
+ {75, 79, 76, 80},
+ },
+ {
+ {84, 80, 83, 79},
+ {78, 82, 77, 81},
+ {82, 78, 83, 79},
+ {76, 80, 77, 81},
+ },
+ {
+ {85, 81, 84, 80},
+ {79, 83, 78, 82},
+ {83, 79, 84, 80},
+ {77, 81, 78, 82},
+ },
+ {
+ {86, 82, 85, 81},
+ {80, 84, 79, 83},
+ {84, 80, 85, 81},
+ {78, 82, 79, 83},
+ },
+ {
+ {87, 83, 86, 82},
+ {81, 85, 80, 84},
+ {85, 81, 86, 82},
+ {79, 83, 80, 84},
+ },
+ {
+ {88, 84, 87, 83},
+ {82, 86, 81, 85},
+ {86, 82, 87, 83},
+ {80, 84, 81, 85},
+ },
+ {
+ {89, 85, 88, 84},
+ {83, 87, 82, 86},
+ {87, 83, 88, 84},
+ {81, 85, 82, 86},
+ },
+ {
+ {90, 86, 89, 85},
+ {84, 88, 83, 87},
+ {88, 84, 89, 85},
+ {82, 86, 83, 87},
+ },
+ {
+ {91, 87, 90, 86},
+ {85, 89, 84, 88},
+ {89, 85, 90, 86},
+ {83, 87, 84, 88},
+ },
+ {
+ {92, 88, 91, 87},
+ {86, 90, 85, 89},
+ {90, 86, 91, 87},
+ {84, 88, 85, 89},
+ },
+ {
+ {93, 89, 92, 88},
+ {87, 91, 86, 90},
+ {91, 87, 92, 88},
+ {85, 89, 86, 90},
+ },
+ {
+ {94, 90, 93, 89},
+ {88, 92, 87, 91},
+ {92, 88, 93, 89},
+ {86, 90, 87, 91},
+ },
+ {
+ {95, 91, 94, 90},
+ {89, 93, 88, 92},
+ {93, 89, 94, 90},
+ {87, 91, 88, 92},
+ },
+ {
+ {96, 92, 95, 91},
+ {90, 94, 89, 93},
+ {94, 90, 95, 91},
+ {88, 92, 89, 93},
+ },
+ {
+ {97, 93, 96, 92},
+ {91, 95, 90, 94},
+ {95, 91, 96, 92},
+ {89, 93, 90, 94},
+ },
+ {
+ {98, 94, 97, 93},
+ {92, 96, 91, 95},
+ {96, 92, 97, 93},
+ {90, 94, 91, 95},
+ },
+ {
+ {99, 95, 98, 94},
+ {93, 97, 92, 96},
+ {97, 93, 98, 94},
+ {91, 95, 92, 96},
+ },
+ {
+ {100, 96, 99, 95},
+ {94, 98, 93, 97},
+ {98, 94, 99, 95},
+ {92, 96, 93, 97},
+ },
+ {
+ {101, 97, 100, 96},
+ {95, 99, 94, 98},
+ {99, 95, 100, 96},
+ {93, 97, 94, 98},
+ },
+ {
+ {102, 98, 101, 97},
+ {96, 100, 95, 99},
+ {100, 96, 101, 97},
+ {94, 98, 95, 99},
+ },
+ {
+ {103, 99, 102, 98},
+ {97, 101, 96, 100},
+ {101, 97, 102, 98},
+ {95, 99, 96, 100},
+ },
+ {
+ {104, 100, 103, 99},
+ {98, 102, 97, 101},
+ {102, 98, 103, 99},
+ {96, 100, 97, 101},
+ },
+ {
+ {105, 101, 104, 100},
+ {99, 103, 98, 102},
+ {103, 99, 104, 100},
+ {97, 101, 98, 102},
+ },
+ {
+ {106, 102, 105, 101},
+ {100, 104, 99, 103},
+ {104, 100, 105, 101},
+ {98, 102, 99, 103},
+ },
+ {
+ {107, 103, 106, 102},
+ {101, 105, 100, 104},
+ {105, 101, 106, 102},
+ {99, 103, 100, 104},
+ },
+ {
+ {108, 104, 107, 103},
+ {102, 106, 101, 105},
+ {106, 102, 107, 103},
+ {100, 104, 101, 105},
+ },
+ {
+ {109, 105, 108, 104},
+ {103, 107, 102, 106},
+ {107, 103, 108, 104},
+ {101, 105, 102, 106},
+ },
+ {
+ {110, 106, 109, 105},
+ {104, 108, 103, 107},
+ {108, 104, 109, 105},
+ {102, 106, 103, 107},
+ },
+ {
+ {111, 107, 110, 106},
+ {105, 109, 104, 108},
+ {109, 105, 110, 106},
+ {103, 107, 104, 108},
+ },
+ {
+ {112, 108, 111, 107},
+ {106, 110, 105, 109},
+ {110, 106, 111, 107},
+ {104, 108, 105, 109},
+ },
+ {
+ {113, 109, 112, 108},
+ {107, 111, 106, 110},
+ {111, 107, 112, 108},
+ {105, 109, 106, 110},
+ },
+ {
+ {114, 110, 113, 109},
+ {108, 112, 107, 111},
+ {112, 108, 113, 109},
+ {106, 110, 107, 111},
+ },
+ {
+ {115, 111, 114, 110},
+ {109, 113, 108, 112},
+ {113, 109, 114, 110},
+ {107, 111, 108, 112},
+ },
+ {
+ {116, 112, 115, 111},
+ {110, 114, 109, 113},
+ {114, 110, 115, 111},
+ {108, 112, 109, 113},
+ },
+ {
+ {117, 113, 116, 112},
+ {111, 115, 110, 114},
+ {115, 111, 116, 112},
+ {109, 113, 110, 114},
+ },
+ {
+ {118, 114, 117, 113},
+ {112, 116, 111, 115},
+ {116, 112, 117, 113},
+ {110, 114, 111, 115},
+ },
+ {
+ {119, 115, 118, 114},
+ {113, 117, 112, 116},
+ {117, 113, 118, 114},
+ {111, 115, 112, 116},
+ },
+ {
+ {120, 116, 119, 115},
+ {114, 118, 113, 117},
+ {118, 114, 119, 115},
+ {112, 116, 113, 117},
+ },
+ {
+ {121, 117, 120, 116},
+ {115, 119, 114, 118},
+ {119, 115, 120, 116},
+ {113, 117, 114, 118},
+ },
+ {
+ {122, 118, 121, 117},
+ {116, 120, 115, 119},
+ {120, 116, 121, 117},
+ {114, 118, 115, 119},
+ },
+ {
+ {123, 119, 122, 118},
+ {117, 121, 116, 120},
+ {121, 117, 122, 118},
+ {115, 119, 116, 120},
+ },
+ {
+ {124, 120, 123, 119},
+ {118, 122, 117, 121},
+ {122, 118, 123, 119},
+ {116, 120, 117, 121},
+ },
+ {
+ {125, 121, 124, 120},
+ {119, 123, 118, 122},
+ {123, 119, 124, 120},
+ {117, 121, 118, 122},
+ },
+ {
+ {126, 122, 125, 121},
+ {120, 124, 119, 123},
+ {124, 120, 125, 121},
+ {118, 122, 119, 123},
+ },
+ {
+ {127, 123, 126, 122},
+ {121, 125, 120, 124},
+ {125, 121, 126, 122},
+ {119, 123, 120, 124},
+ },
+ {
+ {128, 124, 127, 123},
+ {122, 126, 121, 125},
+ {126, 122, 127, 123},
+ {120, 124, 121, 125},
+ },
+ {
+ {129, 125, 128, 124},
+ {123, 127, 122, 126},
+ {127, 123, 128, 124},
+ {121, 125, 122, 126},
+ },
+ {
+ {130, 126, 129, 125},
+ {124, 128, 123, 127},
+ {128, 124, 129, 125},
+ {122, 126, 123, 127},
+ },
+ {
+ {131, 127, 130, 126},
+ {125, 129, 124, 128},
+ {129, 125, 130, 126},
+ {123, 127, 124, 128},
+ },
+ {
+ {132, 128, 131, 127},
+ {126, 130, 125, 129},
+ {130, 126, 131, 127},
+ {124, 128, 125, 129},
+ },
+ {
+ {133, 129, 132, 128},
+ {127, 131, 126, 130},
+ {131, 127, 132, 128},
+ {125, 129, 126, 130},
+ },
+ {
+ {134, 130, 133, 129},
+ {128, 132, 127, 131},
+ {132, 128, 133, 129},
+ {126, 130, 127, 131},
+ },
+ {
+ {135, 131, 134, 130},
+ {129, 133, 128, 132},
+ {133, 129, 134, 130},
+ {127, 131, 128, 132},
+ },
+ {
+ {136, 132, 135, 131},
+ {130, 134, 129, 133},
+ {134, 130, 135, 131},
+ {128, 132, 129, 133},
+ },
+ {
+ {137, 133, 136, 132},
+ {131, 135, 130, 134},
+ {135, 131, 136, 132},
+ {129, 133, 130, 134},
+ },
+ {
+ {138, 134, 137, 133},
+ {132, 136, 131, 135},
+ {136, 132, 137, 133},
+ {130, 134, 131, 135},
+ },
+ {
+ {139, 135, 138, 134},
+ {133, 137, 132, 136},
+ {137, 133, 138, 134},
+ {131, 135, 132, 136},
+ },
+ {
+ {140, 136, 139, 135},
+ {134, 138, 133, 137},
+ {138, 134, 139, 135},
+ {132, 136, 133, 137},
+ },
+ {
+ {141, 137, 140, 136},
+ {135, 139, 134, 138},
+ {139, 135, 140, 136},
+ {133, 137, 134, 138},
+ },
+ {
+ {142, 138, 141, 137},
+ {136, 140, 135, 139},
+ {140, 136, 141, 137},
+ {134, 138, 135, 139},
+ },
+ {
+ {143, 139, 142, 138},
+ {137, 141, 136, 140},
+ {141, 137, 142, 138},
+ {135, 139, 136, 140},
+ },
+ {
+ {144, 140, 143, 139},
+ {138, 142, 137, 141},
+ {142, 138, 143, 139},
+ {136, 140, 137, 141},
+ },
+ {
+ {145, 141, 144, 140},
+ {139, 143, 138, 142},
+ {143, 139, 144, 140},
+ {137, 141, 138, 142},
+ },
+ {
+ {146, 142, 145, 141},
+ {140, 144, 139, 143},
+ {144, 140, 145, 141},
+ {138, 142, 139, 143},
+ },
+ {
+ {147, 143, 146, 142},
+ {141, 145, 140, 144},
+ {145, 141, 146, 142},
+ {139, 143, 140, 144},
+ },
+ {
+ {148, 144, 147, 143},
+ {142, 146, 141, 145},
+ {146, 142, 147, 143},
+ {140, 144, 141, 145},
+ },
+ {
+ {149, 145, 148, 144},
+ {143, 147, 142, 146},
+ {147, 143, 148, 144},
+ {141, 145, 142, 146},
+ },
+ {
+ {150, 146, 149, 145},
+ {144, 148, 143, 147},
+ {148, 144, 149, 145},
+ {142, 146, 143, 147},
+ },
+ {
+ {151, 147, 150, 146},
+ {145, 149, 144, 148},
+ {149, 145, 150, 146},
+ {143, 147, 144, 148},
+ },
+ {
+ {152, 148, 151, 147},
+ {146, 150, 145, 149},
+ {150, 146, 151, 147},
+ {144, 148, 145, 149},
+ },
+ {
+ {153, 149, 152, 148},
+ {147, 151, 146, 150},
+ {151, 147, 152, 148},
+ {145, 149, 146, 150},
+ },
+ {
+ {154, 150, 153, 149},
+ {148, 152, 147, 151},
+ {152, 148, 153, 149},
+ {146, 150, 147, 151},
+ },
+ {
+ {155, 151, 154, 150},
+ {149, 153, 148, 152},
+ {153, 149, 154, 150},
+ {147, 151, 148, 152},
+ },
+ {
+ {156, 152, 155, 151},
+ {150, 154, 149, 153},
+ {154, 150, 155, 151},
+ {148, 152, 149, 153},
+ },
+ {
+ {157, 153, 156, 152},
+ {151, 155, 150, 154},
+ {155, 151, 156, 152},
+ {149, 153, 150, 154},
+ },
+ {
+ {158, 154, 157, 153},
+ {152, 156, 151, 155},
+ {156, 152, 157, 153},
+ {150, 154, 151, 155},
+ },
+ {
+ {159, 155, 158, 154},
+ {153, 157, 152, 156},
+ {157, 153, 158, 154},
+ {151, 155, 152, 156},
+ },
+ {
+ {160, 156, 159, 155},
+ {154, 158, 153, 157},
+ {158, 154, 159, 155},
+ {152, 156, 153, 157},
+ },
+ {
+ {161, 157, 160, 156},
+ {155, 159, 154, 158},
+ {159, 155, 160, 156},
+ {153, 157, 154, 158},
+ },
+ {
+ {162, 158, 161, 157},
+ {156, 160, 155, 159},
+ {160, 156, 161, 157},
+ {154, 158, 155, 159},
+ },
+ {
+ {163, 159, 162, 158},
+ {157, 161, 156, 160},
+ {161, 157, 162, 158},
+ {155, 159, 156, 160},
+ },
+ {
+ {164, 160, 163, 159},
+ {158, 162, 157, 161},
+ {162, 158, 163, 159},
+ {156, 160, 157, 161},
+ },
+ {
+ {165, 161, 164, 160},
+ {159, 163, 158, 162},
+ {163, 159, 164, 160},
+ {157, 161, 158, 162},
+ },
+ {
+ {166, 162, 165, 161},
+ {160, 164, 159, 163},
+ {164, 160, 165, 161},
+ {158, 162, 159, 163},
+ },
+ {
+ {167, 163, 166, 162},
+ {161, 165, 160, 164},
+ {165, 161, 166, 162},
+ {159, 163, 160, 164},
+ },
+ {
+ {168, 164, 167, 163},
+ {162, 166, 161, 165},
+ {166, 162, 167, 163},
+ {160, 164, 161, 165},
+ },
+ {
+ {169, 165, 168, 164},
+ {163, 167, 162, 166},
+ {167, 163, 168, 164},
+ {161, 165, 162, 166},
+ },
+ {
+ {170, 166, 169, 165},
+ {164, 168, 163, 167},
+ {168, 164, 169, 165},
+ {162, 166, 163, 167},
+ },
+ {
+ {171, 167, 170, 166},
+ {165, 169, 164, 168},
+ {169, 165, 170, 166},
+ {163, 167, 164, 168},
+ },
+ {
+ {172, 168, 171, 167},
+ {166, 170, 165, 169},
+ {170, 166, 171, 167},
+ {164, 168, 165, 169},
+ },
+ {
+ {173, 169, 172, 168},
+ {167, 171, 166, 170},
+ {171, 167, 172, 168},
+ {165, 169, 166, 170},
+ },
+ {
+ {174, 170, 173, 169},
+ {168, 172, 167, 171},
+ {172, 168, 173, 169},
+ {166, 170, 167, 171},
+ },
+ {
+ {175, 171, 174, 170},
+ {169, 173, 168, 172},
+ {173, 169, 174, 170},
+ {167, 171, 168, 172},
+ },
+ {
+ {176, 172, 175, 171},
+ {170, 174, 169, 173},
+ {174, 170, 175, 171},
+ {168, 172, 169, 173},
+ },
+ {
+ {177, 173, 176, 172},
+ {171, 175, 170, 174},
+ {175, 171, 176, 172},
+ {169, 173, 170, 174},
+ },
+ {
+ {178, 174, 177, 173},
+ {172, 176, 171, 175},
+ {176, 172, 177, 173},
+ {170, 174, 171, 175},
+ },
+ {
+ {179, 175, 178, 174},
+ {173, 177, 172, 176},
+ {177, 173, 178, 174},
+ {171, 175, 172, 176},
+ },
+ {
+ {180, 176, 179, 175},
+ {174, 178, 173, 177},
+ {178, 174, 179, 175},
+ {172, 176, 173, 177},
+ },
+ {
+ {181, 177, 180, 176},
+ {175, 179, 174, 178},
+ {179, 175, 180, 176},
+ {173, 177, 174, 178},
+ },
+ {
+ {182, 178, 181, 177},
+ {176, 180, 175, 179},
+ {180, 176, 181, 177},
+ {174, 178, 175, 179},
+ },
+ {
+ {183, 179, 182, 178},
+ {177, 181, 176, 180},
+ {181, 177, 182, 178},
+ {175, 179, 176, 180},
+ },
+ {
+ {184, 180, 183, 179},
+ {178, 182, 177, 181},
+ {182, 178, 183, 179},
+ {176, 180, 177, 181},
+ },
+ {
+ {185, 181, 184, 180},
+ {179, 183, 178, 182},
+ {183, 179, 184, 180},
+ {177, 181, 178, 182},
+ },
+ {
+ {186, 182, 185, 181},
+ {180, 184, 179, 183},
+ {184, 180, 185, 181},
+ {178, 182, 179, 183},
+ },
+ {
+ {187, 183, 186, 182},
+ {181, 185, 180, 184},
+ {185, 181, 186, 182},
+ {179, 183, 180, 184},
+ },
+ {
+ {188, 184, 187, 183},
+ {182, 186, 181, 185},
+ {186, 182, 187, 183},
+ {180, 184, 181, 185},
+ },
+ {
+ {189, 185, 188, 184},
+ {183, 187, 182, 186},
+ {187, 183, 188, 184},
+ {181, 185, 182, 186},
+ },
+ {
+ {190, 186, 189, 185},
+ {184, 188, 183, 187},
+ {188, 184, 189, 185},
+ {182, 186, 183, 187},
+ },
+ {
+ {191, 187, 190, 186},
+ {185, 189, 184, 188},
+ {189, 185, 190, 186},
+ {183, 187, 184, 188},
+ },
+ {
+ {192, 188, 191, 187},
+ {186, 190, 185, 189},
+ {190, 186, 191, 187},
+ {184, 188, 185, 189},
+ },
+ {
+ {193, 189, 192, 188},
+ {187, 191, 186, 190},
+ {191, 187, 192, 188},
+ {185, 189, 186, 190},
+ },
+ {
+ {194, 190, 193, 189},
+ {188, 192, 187, 191},
+ {192, 188, 193, 189},
+ {186, 190, 187, 191},
+ },
+ {
+ {195, 191, 194, 190},
+ {189, 193, 188, 192},
+ {193, 189, 194, 190},
+ {187, 191, 188, 192},
+ },
+ {
+ {196, 192, 195, 191},
+ {190, 194, 189, 193},
+ {194, 190, 195, 191},
+ {188, 192, 189, 193},
+ },
+ {
+ {197, 193, 196, 192},
+ {191, 195, 190, 194},
+ {195, 191, 196, 192},
+ {189, 193, 190, 194},
+ },
+ {
+ {198, 194, 197, 193},
+ {192, 196, 191, 195},
+ {196, 192, 197, 193},
+ {190, 194, 191, 195},
+ },
+ {
+ {199, 195, 198, 194},
+ {193, 197, 192, 196},
+ {197, 193, 198, 194},
+ {191, 195, 192, 196},
+ },
+ {
+ {200, 196, 199, 195},
+ {194, 198, 193, 197},
+ {198, 194, 199, 195},
+ {192, 196, 193, 197},
+ },
+ {
+ {201, 197, 200, 196},
+ {195, 199, 194, 198},
+ {199, 195, 200, 196},
+ {193, 197, 194, 198},
+ },
+ {
+ {202, 198, 201, 197},
+ {196, 200, 195, 199},
+ {200, 196, 201, 197},
+ {194, 198, 195, 199},
+ },
+ {
+ {203, 199, 202, 198},
+ {197, 201, 196, 200},
+ {201, 197, 202, 198},
+ {195, 199, 196, 200},
+ },
+ {
+ {204, 200, 203, 199},
+ {198, 202, 197, 201},
+ {202, 198, 203, 199},
+ {196, 200, 197, 201},
+ },
+ {
+ {205, 201, 204, 200},
+ {199, 203, 198, 202},
+ {203, 199, 204, 200},
+ {197, 201, 198, 202},
+ },
+ {
+ {206, 202, 205, 201},
+ {200, 204, 199, 203},
+ {204, 200, 205, 201},
+ {198, 202, 199, 203},
+ },
+ {
+ {207, 203, 206, 202},
+ {201, 205, 200, 204},
+ {205, 201, 206, 202},
+ {199, 203, 200, 204},
+ },
+ {
+ {208, 204, 207, 203},
+ {202, 206, 201, 205},
+ {206, 202, 207, 203},
+ {200, 204, 201, 205},
+ },
+ {
+ {209, 205, 208, 204},
+ {203, 207, 202, 206},
+ {207, 203, 208, 204},
+ {201, 205, 202, 206},
+ },
+ {
+ {210, 206, 209, 205},
+ {204, 208, 203, 207},
+ {208, 204, 209, 205},
+ {202, 206, 203, 207},
+ },
+ {
+ {211, 207, 210, 206},
+ {205, 209, 204, 208},
+ {209, 205, 210, 206},
+ {203, 207, 204, 208},
+ },
+ {
+ {212, 208, 211, 207},
+ {206, 210, 205, 209},
+ {210, 206, 211, 207},
+ {204, 208, 205, 209},
+ },
+ {
+ {213, 209, 212, 208},
+ {207, 211, 206, 210},
+ {211, 207, 212, 208},
+ {205, 209, 206, 210},
+ },
+ {
+ {214, 210, 213, 209},
+ {208, 212, 207, 211},
+ {212, 208, 213, 209},
+ {206, 210, 207, 211},
+ },
+ {
+ {215, 211, 214, 210},
+ {209, 213, 208, 212},
+ {213, 209, 214, 210},
+ {207, 211, 208, 212},
+ },
+ {
+ {216, 212, 215, 211},
+ {210, 214, 209, 213},
+ {214, 210, 215, 211},
+ {208, 212, 209, 213},
+ },
+ {
+ {217, 213, 216, 212},
+ {211, 215, 210, 214},
+ {215, 211, 216, 212},
+ {209, 213, 210, 214},
+ },
+ {
+ {218, 214, 217, 213},
+ {212, 216, 211, 215},
+ {216, 212, 217, 213},
+ {210, 214, 211, 215},
+ },
+ {
+ {219, 215, 218, 214},
+ {213, 217, 212, 216},
+ {217, 213, 218, 214},
+ {211, 215, 212, 216},
+ },
+ {
+ {220, 216, 219, 215},
+ {214, 218, 213, 217},
+ {218, 214, 219, 215},
+ {212, 216, 213, 217},
+ },
+ {
+ {221, 217, 220, 216},
+ {215, 219, 214, 218},
+ {219, 215, 220, 216},
+ {213, 217, 214, 218},
+ },
+ {
+ {222, 218, 221, 217},
+ {216, 220, 215, 219},
+ {220, 216, 221, 217},
+ {214, 218, 215, 219},
+ },
+ {
+ {223, 219, 222, 218},
+ {217, 221, 216, 220},
+ {221, 217, 222, 218},
+ {215, 219, 216, 220},
+ },
+ {
+ {224, 220, 223, 219},
+ {218, 222, 217, 221},
+ {222, 218, 223, 219},
+ {216, 220, 217, 221},
+ },
+ {
+ {225, 221, 224, 220},
+ {219, 223, 218, 222},
+ {223, 219, 224, 220},
+ {217, 221, 218, 222},
+ },
+ {
+ {226, 222, 225, 221},
+ {220, 224, 219, 223},
+ {224, 220, 225, 221},
+ {218, 222, 219, 223},
+ },
+ {
+ {227, 223, 226, 222},
+ {221, 225, 220, 224},
+ {225, 221, 226, 222},
+ {219, 223, 220, 224},
+ },
+ {
+ {228, 224, 227, 223},
+ {222, 226, 221, 225},
+ {226, 222, 227, 223},
+ {220, 224, 221, 225},
+ },
+ {
+ {229, 225, 228, 224},
+ {223, 227, 222, 226},
+ {227, 223, 228, 224},
+ {221, 225, 222, 226},
+ },
+ {
+ {230, 226, 229, 225},
+ {224, 228, 223, 227},
+ {228, 224, 229, 225},
+ {222, 226, 223, 227},
+ },
+ {
+ {231, 227, 230, 226},
+ {225, 229, 224, 228},
+ {229, 225, 230, 226},
+ {223, 227, 224, 228},
+ },
+ {
+ {232, 228, 231, 227},
+ {226, 230, 225, 229},
+ {230, 226, 231, 227},
+ {224, 228, 225, 229},
+ },
+ {
+ {233, 229, 232, 228},
+ {227, 231, 226, 230},
+ {231, 227, 232, 228},
+ {225, 229, 226, 230},
+ },
+ {
+ {234, 230, 233, 229},
+ {228, 232, 227, 231},
+ {232, 228, 233, 229},
+ {226, 230, 227, 231},
+ },
+ {
+ {235, 231, 234, 230},
+ {229, 233, 228, 232},
+ {233, 229, 234, 230},
+ {227, 231, 228, 232},
+ },
+ {
+ {236, 232, 235, 231},
+ {230, 234, 229, 233},
+ {234, 230, 235, 231},
+ {228, 232, 229, 233},
+ },
+ {
+ {237, 233, 236, 232},
+ {231, 235, 230, 234},
+ {235, 231, 236, 232},
+ {229, 233, 230, 234},
+ },
+ {
+ {238, 234, 237, 233},
+ {232, 236, 231, 235},
+ {236, 232, 237, 233},
+ {230, 234, 231, 235},
+ },
+ {
+ {239, 235, 238, 234},
+ {233, 237, 232, 236},
+ {237, 233, 238, 234},
+ {231, 235, 232, 236},
+ },
+ {
+ {240, 236, 239, 235},
+ {234, 238, 233, 237},
+ {238, 234, 239, 235},
+ {232, 236, 233, 237},
+ },
+ {
+ {241, 237, 240, 236},
+ {235, 239, 234, 238},
+ {239, 235, 240, 236},
+ {233, 237, 234, 238},
+ },
+ {
+ {242, 238, 241, 237},
+ {236, 240, 235, 239},
+ {240, 236, 241, 237},
+ {234, 238, 235, 239},
+ },
+ {
+ {243, 239, 242, 238},
+ {237, 241, 236, 240},
+ {241, 237, 242, 238},
+ {235, 239, 236, 240},
+ },
+ {
+ {244, 240, 243, 239},
+ {238, 242, 237, 241},
+ {242, 238, 243, 239},
+ {236, 240, 237, 241},
+ },
+ {
+ {245, 241, 244, 240},
+ {239, 243, 238, 242},
+ {243, 239, 244, 240},
+ {237, 241, 238, 242},
+ },
+ {
+ {246, 242, 245, 241},
+ {240, 244, 239, 243},
+ {244, 240, 245, 241},
+ {238, 242, 239, 243},
+ },
+ {
+ {247, 243, 246, 242},
+ {241, 245, 240, 244},
+ {245, 241, 246, 242},
+ {239, 243, 240, 244},
+ },
+ {
+ {248, 244, 247, 243},
+ {242, 246, 241, 245},
+ {246, 242, 247, 243},
+ {240, 244, 241, 245},
+ },
+ {
+ {249, 245, 248, 244},
+ {243, 247, 242, 246},
+ {247, 243, 248, 244},
+ {241, 245, 242, 246},
+ },
+ {
+ {250, 246, 249, 245},
+ {244, 248, 243, 247},
+ {248, 244, 249, 245},
+ {242, 246, 243, 247},
+ },
+ {
+ {251, 247, 250, 246},
+ {245, 249, 244, 248},
+ {249, 245, 250, 246},
+ {243, 247, 244, 248},
+ },
+ {
+ {252, 248, 251, 247},
+ {246, 250, 245, 249},
+ {250, 246, 251, 247},
+ {244, 248, 245, 249},
+ },
+ {
+ {253, 249, 252, 248},
+ {247, 251, 246, 250},
+ {251, 247, 252, 248},
+ {245, 249, 246, 250},
+ },
+ {
+ {254, 250, 253, 249},
+ {248, 252, 247, 251},
+ {252, 248, 253, 249},
+ {246, 250, 247, 251},
+ },
+ {
+ {255, 251, 254, 250},
+ {249, 253, 248, 252},
+ {253, 249, 254, 250},
+ {247, 251, 248, 252},
+ },
+ {
+ {255, 252, 255, 251},
+ {250, 254, 249, 253},
+ {254, 250, 255, 251},
+ {248, 252, 249, 253},
+ },
+ {
+ {255, 253, 255, 252},
+ {251, 255, 250, 254},
+ {255, 251, 255, 252},
+ {249, 253, 250, 254},
+ },
+ {
+ {255, 254, 255, 253},
+ {252, 255, 251, 255},
+ {255, 252, 255, 253},
+ {250, 254, 251, 255},
+ },
+ {
+ {255, 255, 255, 254},
+ {253, 255, 252, 255},
+ {255, 253, 255, 254},
+ {251, 255, 252, 255},
+ },
+ {
+ {255, 255, 255, 255},
+ {254, 255, 253, 255},
+ {255, 254, 255, 255},
+ {252, 255, 253, 255},
+ },
+};
+
+static const uint8_t dithersub_g[256][4][4] =
+{
+ {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ },
+ {
+ {5, 3, 4, 2},
+ {2, 4, 1, 3},
+ {4, 2, 4, 2},
+ {1, 3, 1, 3},
+ },
+ {
+ {6, 4, 5, 3},
+ {3, 5, 2, 4},
+ {5, 3, 5, 3},
+ {2, 4, 2, 4},
+ },
+ {
+ {7, 5, 6, 4},
+ {4, 6, 3, 5},
+ {6, 4, 6, 4},
+ {3, 5, 3, 5},
+ },
+ {
+ {8, 6, 7, 5},
+ {5, 7, 4, 6},
+ {7, 5, 7, 5},
+ {4, 6, 4, 6},
+ },
+ {
+ {9, 7, 8, 6},
+ {6, 8, 5, 7},
+ {8, 6, 8, 6},
+ {5, 7, 5, 7},
+ },
+ {
+ {10, 8, 9, 7},
+ {7, 9, 6, 8},
+ {9, 7, 9, 7},
+ {6, 8, 6, 8},
+ },
+ {
+ {11, 9, 10, 8},
+ {8, 10, 7, 9},
+ {10, 8, 10, 8},
+ {7, 9, 7, 9},
+ },
+ {
+ {12, 10, 11, 9},
+ {9, 11, 8, 10},
+ {11, 9, 11, 9},
+ {8, 10, 8, 10},
+ },
+ {
+ {13, 11, 12, 10},
+ {10, 12, 9, 11},
+ {12, 10, 12, 10},
+ {9, 11, 9, 11},
+ },
+ {
+ {14, 12, 13, 11},
+ {11, 13, 10, 12},
+ {13, 11, 13, 11},
+ {10, 12, 10, 12},
+ },
+ {
+ {15, 13, 14, 12},
+ {12, 14, 11, 13},
+ {14, 12, 14, 12},
+ {11, 13, 11, 13},
+ },
+ {
+ {16, 14, 15, 13},
+ {13, 15, 12, 14},
+ {15, 13, 15, 13},
+ {12, 14, 12, 14},
+ },
+ {
+ {17, 15, 16, 14},
+ {14, 16, 13, 15},
+ {16, 14, 16, 14},
+ {13, 15, 13, 15},
+ },
+ {
+ {18, 16, 17, 15},
+ {15, 17, 14, 16},
+ {17, 15, 17, 15},
+ {14, 16, 14, 16},
+ },
+ {
+ {19, 17, 18, 16},
+ {16, 18, 15, 17},
+ {18, 16, 18, 16},
+ {15, 17, 15, 17},
+ },
+ {
+ {20, 18, 19, 17},
+ {17, 19, 16, 18},
+ {19, 17, 19, 17},
+ {16, 18, 16, 18},
+ },
+ {
+ {21, 19, 20, 18},
+ {18, 20, 17, 19},
+ {20, 18, 20, 18},
+ {17, 19, 17, 19},
+ },
+ {
+ {22, 20, 21, 19},
+ {19, 21, 18, 20},
+ {21, 19, 21, 19},
+ {18, 20, 18, 20},
+ },
+ {
+ {23, 21, 22, 20},
+ {20, 22, 19, 21},
+ {22, 20, 22, 20},
+ {19, 21, 19, 21},
+ },
+ {
+ {24, 22, 23, 21},
+ {21, 23, 20, 22},
+ {23, 21, 23, 21},
+ {20, 22, 20, 22},
+ },
+ {
+ {25, 23, 24, 22},
+ {22, 24, 21, 23},
+ {24, 22, 24, 22},
+ {21, 23, 21, 23},
+ },
+ {
+ {26, 24, 25, 23},
+ {23, 25, 22, 24},
+ {25, 23, 25, 23},
+ {22, 24, 22, 24},
+ },
+ {
+ {27, 25, 26, 24},
+ {24, 26, 23, 25},
+ {26, 24, 26, 24},
+ {23, 25, 23, 25},
+ },
+ {
+ {28, 26, 27, 25},
+ {25, 27, 24, 26},
+ {27, 25, 27, 25},
+ {24, 26, 24, 26},
+ },
+ {
+ {29, 27, 28, 26},
+ {26, 28, 25, 27},
+ {28, 26, 28, 26},
+ {25, 27, 25, 27},
+ },
+ {
+ {30, 28, 29, 27},
+ {27, 29, 26, 28},
+ {29, 27, 29, 27},
+ {26, 28, 26, 28},
+ },
+ {
+ {31, 29, 30, 28},
+ {28, 30, 27, 29},
+ {30, 28, 30, 28},
+ {27, 29, 27, 29},
+ },
+ {
+ {32, 30, 31, 29},
+ {29, 31, 28, 30},
+ {31, 29, 31, 29},
+ {28, 30, 28, 30},
+ },
+ {
+ {33, 31, 32, 30},
+ {30, 32, 29, 31},
+ {32, 30, 32, 30},
+ {29, 31, 29, 31},
+ },
+ {
+ {34, 32, 33, 31},
+ {31, 33, 30, 32},
+ {33, 31, 33, 31},
+ {30, 32, 30, 32},
+ },
+ {
+ {35, 33, 34, 32},
+ {32, 34, 31, 33},
+ {34, 32, 34, 32},
+ {31, 33, 31, 33},
+ },
+ {
+ {36, 34, 35, 33},
+ {33, 35, 32, 34},
+ {35, 33, 35, 33},
+ {32, 34, 32, 34},
+ },
+ {
+ {37, 35, 36, 34},
+ {34, 36, 33, 35},
+ {36, 34, 36, 34},
+ {33, 35, 33, 35},
+ },
+ {
+ {38, 36, 37, 35},
+ {35, 37, 34, 36},
+ {37, 35, 37, 35},
+ {34, 36, 34, 36},
+ },
+ {
+ {39, 37, 38, 36},
+ {36, 38, 35, 37},
+ {38, 36, 38, 36},
+ {35, 37, 35, 37},
+ },
+ {
+ {40, 38, 39, 37},
+ {37, 39, 36, 38},
+ {39, 37, 39, 37},
+ {36, 38, 36, 38},
+ },
+ {
+ {41, 39, 40, 38},
+ {38, 40, 37, 39},
+ {40, 38, 40, 38},
+ {37, 39, 37, 39},
+ },
+ {
+ {42, 40, 41, 39},
+ {39, 41, 38, 40},
+ {41, 39, 41, 39},
+ {38, 40, 38, 40},
+ },
+ {
+ {43, 41, 42, 40},
+ {40, 42, 39, 41},
+ {42, 40, 42, 40},
+ {39, 41, 39, 41},
+ },
+ {
+ {44, 42, 43, 41},
+ {41, 43, 40, 42},
+ {43, 41, 43, 41},
+ {40, 42, 40, 42},
+ },
+ {
+ {45, 43, 44, 42},
+ {42, 44, 41, 43},
+ {44, 42, 44, 42},
+ {41, 43, 41, 43},
+ },
+ {
+ {46, 44, 45, 43},
+ {43, 45, 42, 44},
+ {45, 43, 45, 43},
+ {42, 44, 42, 44},
+ },
+ {
+ {47, 45, 46, 44},
+ {44, 46, 43, 45},
+ {46, 44, 46, 44},
+ {43, 45, 43, 45},
+ },
+ {
+ {48, 46, 47, 45},
+ {45, 47, 44, 46},
+ {47, 45, 47, 45},
+ {44, 46, 44, 46},
+ },
+ {
+ {49, 47, 48, 46},
+ {46, 48, 45, 47},
+ {48, 46, 48, 46},
+ {45, 47, 45, 47},
+ },
+ {
+ {50, 48, 49, 47},
+ {47, 49, 46, 48},
+ {49, 47, 49, 47},
+ {46, 48, 46, 48},
+ },
+ {
+ {51, 49, 50, 48},
+ {48, 50, 47, 49},
+ {50, 48, 50, 48},
+ {47, 49, 47, 49},
+ },
+ {
+ {52, 50, 51, 49},
+ {49, 51, 48, 50},
+ {51, 49, 51, 49},
+ {48, 50, 48, 50},
+ },
+ {
+ {53, 51, 52, 50},
+ {50, 52, 49, 51},
+ {52, 50, 52, 50},
+ {49, 51, 49, 51},
+ },
+ {
+ {54, 52, 53, 51},
+ {51, 53, 50, 52},
+ {53, 51, 53, 51},
+ {50, 52, 50, 52},
+ },
+ {
+ {55, 53, 54, 52},
+ {52, 54, 51, 53},
+ {54, 52, 54, 52},
+ {51, 53, 51, 53},
+ },
+ {
+ {56, 54, 55, 53},
+ {53, 55, 52, 54},
+ {55, 53, 55, 53},
+ {52, 54, 52, 54},
+ },
+ {
+ {57, 55, 56, 54},
+ {54, 56, 53, 55},
+ {56, 54, 56, 54},
+ {53, 55, 53, 55},
+ },
+ {
+ {58, 56, 57, 55},
+ {55, 57, 54, 56},
+ {57, 55, 57, 55},
+ {54, 56, 54, 56},
+ },
+ {
+ {59, 57, 58, 56},
+ {56, 58, 55, 57},
+ {58, 56, 58, 56},
+ {55, 57, 55, 57},
+ },
+ {
+ {60, 58, 59, 57},
+ {57, 59, 56, 58},
+ {59, 57, 59, 57},
+ {56, 58, 56, 58},
+ },
+ {
+ {61, 59, 60, 58},
+ {58, 60, 57, 59},
+ {60, 58, 60, 58},
+ {57, 59, 57, 59},
+ },
+ {
+ {62, 60, 61, 59},
+ {59, 61, 58, 60},
+ {61, 59, 61, 59},
+ {58, 60, 58, 60},
+ },
+ {
+ {63, 61, 62, 60},
+ {60, 62, 59, 61},
+ {62, 60, 62, 60},
+ {59, 61, 59, 61},
+ },
+ {
+ {64, 62, 63, 61},
+ {61, 63, 60, 62},
+ {63, 61, 63, 61},
+ {60, 62, 60, 62},
+ },
+ {
+ {65, 63, 64, 62},
+ {62, 64, 61, 63},
+ {64, 62, 64, 62},
+ {61, 63, 61, 63},
+ },
+ {
+ {66, 64, 65, 63},
+ {63, 65, 62, 64},
+ {65, 63, 65, 63},
+ {62, 64, 62, 64},
+ },
+ {
+ {67, 65, 66, 64},
+ {64, 66, 63, 65},
+ {66, 64, 66, 64},
+ {63, 65, 63, 65},
+ },
+ {
+ {68, 66, 67, 65},
+ {65, 67, 64, 66},
+ {67, 65, 67, 65},
+ {64, 66, 64, 66},
+ },
+ {
+ {69, 67, 68, 66},
+ {66, 68, 65, 67},
+ {68, 66, 68, 66},
+ {65, 67, 65, 67},
+ },
+ {
+ {70, 68, 69, 67},
+ {67, 69, 66, 68},
+ {69, 67, 69, 67},
+ {66, 68, 66, 68},
+ },
+ {
+ {71, 69, 70, 68},
+ {68, 70, 67, 69},
+ {70, 68, 70, 68},
+ {67, 69, 67, 69},
+ },
+ {
+ {72, 70, 71, 69},
+ {69, 71, 68, 70},
+ {71, 69, 71, 69},
+ {68, 70, 68, 70},
+ },
+ {
+ {73, 71, 72, 70},
+ {70, 72, 69, 71},
+ {72, 70, 72, 70},
+ {69, 71, 69, 71},
+ },
+ {
+ {74, 72, 73, 71},
+ {71, 73, 70, 72},
+ {73, 71, 73, 71},
+ {70, 72, 70, 72},
+ },
+ {
+ {75, 73, 74, 72},
+ {72, 74, 71, 73},
+ {74, 72, 74, 72},
+ {71, 73, 71, 73},
+ },
+ {
+ {76, 74, 75, 73},
+ {73, 75, 72, 74},
+ {75, 73, 75, 73},
+ {72, 74, 72, 74},
+ },
+ {
+ {77, 75, 76, 74},
+ {74, 76, 73, 75},
+ {76, 74, 76, 74},
+ {73, 75, 73, 75},
+ },
+ {
+ {78, 76, 77, 75},
+ {75, 77, 74, 76},
+ {77, 75, 77, 75},
+ {74, 76, 74, 76},
+ },
+ {
+ {79, 77, 78, 76},
+ {76, 78, 75, 77},
+ {78, 76, 78, 76},
+ {75, 77, 75, 77},
+ },
+ {
+ {80, 78, 79, 77},
+ {77, 79, 76, 78},
+ {79, 77, 79, 77},
+ {76, 78, 76, 78},
+ },
+ {
+ {81, 79, 80, 78},
+ {78, 80, 77, 79},
+ {80, 78, 80, 78},
+ {77, 79, 77, 79},
+ },
+ {
+ {82, 80, 81, 79},
+ {79, 81, 78, 80},
+ {81, 79, 81, 79},
+ {78, 80, 78, 80},
+ },
+ {
+ {83, 81, 82, 80},
+ {80, 82, 79, 81},
+ {82, 80, 82, 80},
+ {79, 81, 79, 81},
+ },
+ {
+ {84, 82, 83, 81},
+ {81, 83, 80, 82},
+ {83, 81, 83, 81},
+ {80, 82, 80, 82},
+ },
+ {
+ {85, 83, 84, 82},
+ {82, 84, 81, 83},
+ {84, 82, 84, 82},
+ {81, 83, 81, 83},
+ },
+ {
+ {86, 84, 85, 83},
+ {83, 85, 82, 84},
+ {85, 83, 85, 83},
+ {82, 84, 82, 84},
+ },
+ {
+ {87, 85, 86, 84},
+ {84, 86, 83, 85},
+ {86, 84, 86, 84},
+ {83, 85, 83, 85},
+ },
+ {
+ {88, 86, 87, 85},
+ {85, 87, 84, 86},
+ {87, 85, 87, 85},
+ {84, 86, 84, 86},
+ },
+ {
+ {89, 87, 88, 86},
+ {86, 88, 85, 87},
+ {88, 86, 88, 86},
+ {85, 87, 85, 87},
+ },
+ {
+ {90, 88, 89, 87},
+ {87, 89, 86, 88},
+ {89, 87, 89, 87},
+ {86, 88, 86, 88},
+ },
+ {
+ {91, 89, 90, 88},
+ {88, 90, 87, 89},
+ {90, 88, 90, 88},
+ {87, 89, 87, 89},
+ },
+ {
+ {92, 90, 91, 89},
+ {89, 91, 88, 90},
+ {91, 89, 91, 89},
+ {88, 90, 88, 90},
+ },
+ {
+ {93, 91, 92, 90},
+ {90, 92, 89, 91},
+ {92, 90, 92, 90},
+ {89, 91, 89, 91},
+ },
+ {
+ {94, 92, 93, 91},
+ {91, 93, 90, 92},
+ {93, 91, 93, 91},
+ {90, 92, 90, 92},
+ },
+ {
+ {95, 93, 94, 92},
+ {92, 94, 91, 93},
+ {94, 92, 94, 92},
+ {91, 93, 91, 93},
+ },
+ {
+ {96, 94, 95, 93},
+ {93, 95, 92, 94},
+ {95, 93, 95, 93},
+ {92, 94, 92, 94},
+ },
+ {
+ {97, 95, 96, 94},
+ {94, 96, 93, 95},
+ {96, 94, 96, 94},
+ {93, 95, 93, 95},
+ },
+ {
+ {98, 96, 97, 95},
+ {95, 97, 94, 96},
+ {97, 95, 97, 95},
+ {94, 96, 94, 96},
+ },
+ {
+ {99, 97, 98, 96},
+ {96, 98, 95, 97},
+ {98, 96, 98, 96},
+ {95, 97, 95, 97},
+ },
+ {
+ {100, 98, 99, 97},
+ {97, 99, 96, 98},
+ {99, 97, 99, 97},
+ {96, 98, 96, 98},
+ },
+ {
+ {101, 99, 100, 98},
+ {98, 100, 97, 99},
+ {100, 98, 100, 98},
+ {97, 99, 97, 99},
+ },
+ {
+ {102, 100, 101, 99},
+ {99, 101, 98, 100},
+ {101, 99, 101, 99},
+ {98, 100, 98, 100},
+ },
+ {
+ {103, 101, 102, 100},
+ {100, 102, 99, 101},
+ {102, 100, 102, 100},
+ {99, 101, 99, 101},
+ },
+ {
+ {104, 102, 103, 101},
+ {101, 103, 100, 102},
+ {103, 101, 103, 101},
+ {100, 102, 100, 102},
+ },
+ {
+ {105, 103, 104, 102},
+ {102, 104, 101, 103},
+ {104, 102, 104, 102},
+ {101, 103, 101, 103},
+ },
+ {
+ {106, 104, 105, 103},
+ {103, 105, 102, 104},
+ {105, 103, 105, 103},
+ {102, 104, 102, 104},
+ },
+ {
+ {107, 105, 106, 104},
+ {104, 106, 103, 105},
+ {106, 104, 106, 104},
+ {103, 105, 103, 105},
+ },
+ {
+ {108, 106, 107, 105},
+ {105, 107, 104, 106},
+ {107, 105, 107, 105},
+ {104, 106, 104, 106},
+ },
+ {
+ {109, 107, 108, 106},
+ {106, 108, 105, 107},
+ {108, 106, 108, 106},
+ {105, 107, 105, 107},
+ },
+ {
+ {110, 108, 109, 107},
+ {107, 109, 106, 108},
+ {109, 107, 109, 107},
+ {106, 108, 106, 108},
+ },
+ {
+ {111, 109, 110, 108},
+ {108, 110, 107, 109},
+ {110, 108, 110, 108},
+ {107, 109, 107, 109},
+ },
+ {
+ {112, 110, 111, 109},
+ {109, 111, 108, 110},
+ {111, 109, 111, 109},
+ {108, 110, 108, 110},
+ },
+ {
+ {113, 111, 112, 110},
+ {110, 112, 109, 111},
+ {112, 110, 112, 110},
+ {109, 111, 109, 111},
+ },
+ {
+ {114, 112, 113, 111},
+ {111, 113, 110, 112},
+ {113, 111, 113, 111},
+ {110, 112, 110, 112},
+ },
+ {
+ {115, 113, 114, 112},
+ {112, 114, 111, 113},
+ {114, 112, 114, 112},
+ {111, 113, 111, 113},
+ },
+ {
+ {116, 114, 115, 113},
+ {113, 115, 112, 114},
+ {115, 113, 115, 113},
+ {112, 114, 112, 114},
+ },
+ {
+ {117, 115, 116, 114},
+ {114, 116, 113, 115},
+ {116, 114, 116, 114},
+ {113, 115, 113, 115},
+ },
+ {
+ {118, 116, 117, 115},
+ {115, 117, 114, 116},
+ {117, 115, 117, 115},
+ {114, 116, 114, 116},
+ },
+ {
+ {119, 117, 118, 116},
+ {116, 118, 115, 117},
+ {118, 116, 118, 116},
+ {115, 117, 115, 117},
+ },
+ {
+ {120, 118, 119, 117},
+ {117, 119, 116, 118},
+ {119, 117, 119, 117},
+ {116, 118, 116, 118},
+ },
+ {
+ {121, 119, 120, 118},
+ {118, 120, 117, 119},
+ {120, 118, 120, 118},
+ {117, 119, 117, 119},
+ },
+ {
+ {122, 120, 121, 119},
+ {119, 121, 118, 120},
+ {121, 119, 121, 119},
+ {118, 120, 118, 120},
+ },
+ {
+ {123, 121, 122, 120},
+ {120, 122, 119, 121},
+ {122, 120, 122, 120},
+ {119, 121, 119, 121},
+ },
+ {
+ {124, 122, 123, 121},
+ {121, 123, 120, 122},
+ {123, 121, 123, 121},
+ {120, 122, 120, 122},
+ },
+ {
+ {125, 123, 124, 122},
+ {122, 124, 121, 123},
+ {124, 122, 124, 122},
+ {121, 123, 121, 123},
+ },
+ {
+ {126, 124, 125, 123},
+ {123, 125, 122, 124},
+ {125, 123, 125, 123},
+ {122, 124, 122, 124},
+ },
+ {
+ {127, 125, 126, 124},
+ {124, 126, 123, 125},
+ {126, 124, 126, 124},
+ {123, 125, 123, 125},
+ },
+ {
+ {128, 126, 127, 125},
+ {125, 127, 124, 126},
+ {127, 125, 127, 125},
+ {124, 126, 124, 126},
+ },
+ {
+ {129, 127, 128, 126},
+ {126, 128, 125, 127},
+ {128, 126, 128, 126},
+ {125, 127, 125, 127},
+ },
+ {
+ {130, 128, 129, 127},
+ {127, 129, 126, 128},
+ {129, 127, 129, 127},
+ {126, 128, 126, 128},
+ },
+ {
+ {131, 129, 130, 128},
+ {128, 130, 127, 129},
+ {130, 128, 130, 128},
+ {127, 129, 127, 129},
+ },
+ {
+ {132, 130, 131, 129},
+ {129, 131, 128, 130},
+ {131, 129, 131, 129},
+ {128, 130, 128, 130},
+ },
+ {
+ {133, 131, 132, 130},
+ {130, 132, 129, 131},
+ {132, 130, 132, 130},
+ {129, 131, 129, 131},
+ },
+ {
+ {134, 132, 133, 131},
+ {131, 133, 130, 132},
+ {133, 131, 133, 131},
+ {130, 132, 130, 132},
+ },
+ {
+ {135, 133, 134, 132},
+ {132, 134, 131, 133},
+ {134, 132, 134, 132},
+ {131, 133, 131, 133},
+ },
+ {
+ {136, 134, 135, 133},
+ {133, 135, 132, 134},
+ {135, 133, 135, 133},
+ {132, 134, 132, 134},
+ },
+ {
+ {137, 135, 136, 134},
+ {134, 136, 133, 135},
+ {136, 134, 136, 134},
+ {133, 135, 133, 135},
+ },
+ {
+ {138, 136, 137, 135},
+ {135, 137, 134, 136},
+ {137, 135, 137, 135},
+ {134, 136, 134, 136},
+ },
+ {
+ {139, 137, 138, 136},
+ {136, 138, 135, 137},
+ {138, 136, 138, 136},
+ {135, 137, 135, 137},
+ },
+ {
+ {140, 138, 139, 137},
+ {137, 139, 136, 138},
+ {139, 137, 139, 137},
+ {136, 138, 136, 138},
+ },
+ {
+ {141, 139, 140, 138},
+ {138, 140, 137, 139},
+ {140, 138, 140, 138},
+ {137, 139, 137, 139},
+ },
+ {
+ {142, 140, 141, 139},
+ {139, 141, 138, 140},
+ {141, 139, 141, 139},
+ {138, 140, 138, 140},
+ },
+ {
+ {143, 141, 142, 140},
+ {140, 142, 139, 141},
+ {142, 140, 142, 140},
+ {139, 141, 139, 141},
+ },
+ {
+ {144, 142, 143, 141},
+ {141, 143, 140, 142},
+ {143, 141, 143, 141},
+ {140, 142, 140, 142},
+ },
+ {
+ {145, 143, 144, 142},
+ {142, 144, 141, 143},
+ {144, 142, 144, 142},
+ {141, 143, 141, 143},
+ },
+ {
+ {146, 144, 145, 143},
+ {143, 145, 142, 144},
+ {145, 143, 145, 143},
+ {142, 144, 142, 144},
+ },
+ {
+ {147, 145, 146, 144},
+ {144, 146, 143, 145},
+ {146, 144, 146, 144},
+ {143, 145, 143, 145},
+ },
+ {
+ {148, 146, 147, 145},
+ {145, 147, 144, 146},
+ {147, 145, 147, 145},
+ {144, 146, 144, 146},
+ },
+ {
+ {149, 147, 148, 146},
+ {146, 148, 145, 147},
+ {148, 146, 148, 146},
+ {145, 147, 145, 147},
+ },
+ {
+ {150, 148, 149, 147},
+ {147, 149, 146, 148},
+ {149, 147, 149, 147},
+ {146, 148, 146, 148},
+ },
+ {
+ {151, 149, 150, 148},
+ {148, 150, 147, 149},
+ {150, 148, 150, 148},
+ {147, 149, 147, 149},
+ },
+ {
+ {152, 150, 151, 149},
+ {149, 151, 148, 150},
+ {151, 149, 151, 149},
+ {148, 150, 148, 150},
+ },
+ {
+ {153, 151, 152, 150},
+ {150, 152, 149, 151},
+ {152, 150, 152, 150},
+ {149, 151, 149, 151},
+ },
+ {
+ {154, 152, 153, 151},
+ {151, 153, 150, 152},
+ {153, 151, 153, 151},
+ {150, 152, 150, 152},
+ },
+ {
+ {155, 153, 154, 152},
+ {152, 154, 151, 153},
+ {154, 152, 154, 152},
+ {151, 153, 151, 153},
+ },
+ {
+ {156, 154, 155, 153},
+ {153, 155, 152, 154},
+ {155, 153, 155, 153},
+ {152, 154, 152, 154},
+ },
+ {
+ {157, 155, 156, 154},
+ {154, 156, 153, 155},
+ {156, 154, 156, 154},
+ {153, 155, 153, 155},
+ },
+ {
+ {158, 156, 157, 155},
+ {155, 157, 154, 156},
+ {157, 155, 157, 155},
+ {154, 156, 154, 156},
+ },
+ {
+ {159, 157, 158, 156},
+ {156, 158, 155, 157},
+ {158, 156, 158, 156},
+ {155, 157, 155, 157},
+ },
+ {
+ {160, 158, 159, 157},
+ {157, 159, 156, 158},
+ {159, 157, 159, 157},
+ {156, 158, 156, 158},
+ },
+ {
+ {161, 159, 160, 158},
+ {158, 160, 157, 159},
+ {160, 158, 160, 158},
+ {157, 159, 157, 159},
+ },
+ {
+ {162, 160, 161, 159},
+ {159, 161, 158, 160},
+ {161, 159, 161, 159},
+ {158, 160, 158, 160},
+ },
+ {
+ {163, 161, 162, 160},
+ {160, 162, 159, 161},
+ {162, 160, 162, 160},
+ {159, 161, 159, 161},
+ },
+ {
+ {164, 162, 163, 161},
+ {161, 163, 160, 162},
+ {163, 161, 163, 161},
+ {160, 162, 160, 162},
+ },
+ {
+ {165, 163, 164, 162},
+ {162, 164, 161, 163},
+ {164, 162, 164, 162},
+ {161, 163, 161, 163},
+ },
+ {
+ {166, 164, 165, 163},
+ {163, 165, 162, 164},
+ {165, 163, 165, 163},
+ {162, 164, 162, 164},
+ },
+ {
+ {167, 165, 166, 164},
+ {164, 166, 163, 165},
+ {166, 164, 166, 164},
+ {163, 165, 163, 165},
+ },
+ {
+ {168, 166, 167, 165},
+ {165, 167, 164, 166},
+ {167, 165, 167, 165},
+ {164, 166, 164, 166},
+ },
+ {
+ {169, 167, 168, 166},
+ {166, 168, 165, 167},
+ {168, 166, 168, 166},
+ {165, 167, 165, 167},
+ },
+ {
+ {170, 168, 169, 167},
+ {167, 169, 166, 168},
+ {169, 167, 169, 167},
+ {166, 168, 166, 168},
+ },
+ {
+ {171, 169, 170, 168},
+ {168, 170, 167, 169},
+ {170, 168, 170, 168},
+ {167, 169, 167, 169},
+ },
+ {
+ {172, 170, 171, 169},
+ {169, 171, 168, 170},
+ {171, 169, 171, 169},
+ {168, 170, 168, 170},
+ },
+ {
+ {173, 171, 172, 170},
+ {170, 172, 169, 171},
+ {172, 170, 172, 170},
+ {169, 171, 169, 171},
+ },
+ {
+ {174, 172, 173, 171},
+ {171, 173, 170, 172},
+ {173, 171, 173, 171},
+ {170, 172, 170, 172},
+ },
+ {
+ {175, 173, 174, 172},
+ {172, 174, 171, 173},
+ {174, 172, 174, 172},
+ {171, 173, 171, 173},
+ },
+ {
+ {176, 174, 175, 173},
+ {173, 175, 172, 174},
+ {175, 173, 175, 173},
+ {172, 174, 172, 174},
+ },
+ {
+ {177, 175, 176, 174},
+ {174, 176, 173, 175},
+ {176, 174, 176, 174},
+ {173, 175, 173, 175},
+ },
+ {
+ {178, 176, 177, 175},
+ {175, 177, 174, 176},
+ {177, 175, 177, 175},
+ {174, 176, 174, 176},
+ },
+ {
+ {179, 177, 178, 176},
+ {176, 178, 175, 177},
+ {178, 176, 178, 176},
+ {175, 177, 175, 177},
+ },
+ {
+ {180, 178, 179, 177},
+ {177, 179, 176, 178},
+ {179, 177, 179, 177},
+ {176, 178, 176, 178},
+ },
+ {
+ {181, 179, 180, 178},
+ {178, 180, 177, 179},
+ {180, 178, 180, 178},
+ {177, 179, 177, 179},
+ },
+ {
+ {182, 180, 181, 179},
+ {179, 181, 178, 180},
+ {181, 179, 181, 179},
+ {178, 180, 178, 180},
+ },
+ {
+ {183, 181, 182, 180},
+ {180, 182, 179, 181},
+ {182, 180, 182, 180},
+ {179, 181, 179, 181},
+ },
+ {
+ {184, 182, 183, 181},
+ {181, 183, 180, 182},
+ {183, 181, 183, 181},
+ {180, 182, 180, 182},
+ },
+ {
+ {185, 183, 184, 182},
+ {182, 184, 181, 183},
+ {184, 182, 184, 182},
+ {181, 183, 181, 183},
+ },
+ {
+ {186, 184, 185, 183},
+ {183, 185, 182, 184},
+ {185, 183, 185, 183},
+ {182, 184, 182, 184},
+ },
+ {
+ {187, 185, 186, 184},
+ {184, 186, 183, 185},
+ {186, 184, 186, 184},
+ {183, 185, 183, 185},
+ },
+ {
+ {188, 186, 187, 185},
+ {185, 187, 184, 186},
+ {187, 185, 187, 185},
+ {184, 186, 184, 186},
+ },
+ {
+ {189, 187, 188, 186},
+ {186, 188, 185, 187},
+ {188, 186, 188, 186},
+ {185, 187, 185, 187},
+ },
+ {
+ {190, 188, 189, 187},
+ {187, 189, 186, 188},
+ {189, 187, 189, 187},
+ {186, 188, 186, 188},
+ },
+ {
+ {191, 189, 190, 188},
+ {188, 190, 187, 189},
+ {190, 188, 190, 188},
+ {187, 189, 187, 189},
+ },
+ {
+ {192, 190, 191, 189},
+ {189, 191, 188, 190},
+ {191, 189, 191, 189},
+ {188, 190, 188, 190},
+ },
+ {
+ {193, 191, 192, 190},
+ {190, 192, 189, 191},
+ {192, 190, 192, 190},
+ {189, 191, 189, 191},
+ },
+ {
+ {194, 192, 193, 191},
+ {191, 193, 190, 192},
+ {193, 191, 193, 191},
+ {190, 192, 190, 192},
+ },
+ {
+ {195, 193, 194, 192},
+ {192, 194, 191, 193},
+ {194, 192, 194, 192},
+ {191, 193, 191, 193},
+ },
+ {
+ {196, 194, 195, 193},
+ {193, 195, 192, 194},
+ {195, 193, 195, 193},
+ {192, 194, 192, 194},
+ },
+ {
+ {197, 195, 196, 194},
+ {194, 196, 193, 195},
+ {196, 194, 196, 194},
+ {193, 195, 193, 195},
+ },
+ {
+ {198, 196, 197, 195},
+ {195, 197, 194, 196},
+ {197, 195, 197, 195},
+ {194, 196, 194, 196},
+ },
+ {
+ {199, 197, 198, 196},
+ {196, 198, 195, 197},
+ {198, 196, 198, 196},
+ {195, 197, 195, 197},
+ },
+ {
+ {200, 198, 199, 197},
+ {197, 199, 196, 198},
+ {199, 197, 199, 197},
+ {196, 198, 196, 198},
+ },
+ {
+ {201, 199, 200, 198},
+ {198, 200, 197, 199},
+ {200, 198, 200, 198},
+ {197, 199, 197, 199},
+ },
+ {
+ {202, 200, 201, 199},
+ {199, 201, 198, 200},
+ {201, 199, 201, 199},
+ {198, 200, 198, 200},
+ },
+ {
+ {203, 201, 202, 200},
+ {200, 202, 199, 201},
+ {202, 200, 202, 200},
+ {199, 201, 199, 201},
+ },
+ {
+ {204, 202, 203, 201},
+ {201, 203, 200, 202},
+ {203, 201, 203, 201},
+ {200, 202, 200, 202},
+ },
+ {
+ {205, 203, 204, 202},
+ {202, 204, 201, 203},
+ {204, 202, 204, 202},
+ {201, 203, 201, 203},
+ },
+ {
+ {206, 204, 205, 203},
+ {203, 205, 202, 204},
+ {205, 203, 205, 203},
+ {202, 204, 202, 204},
+ },
+ {
+ {207, 205, 206, 204},
+ {204, 206, 203, 205},
+ {206, 204, 206, 204},
+ {203, 205, 203, 205},
+ },
+ {
+ {208, 206, 207, 205},
+ {205, 207, 204, 206},
+ {207, 205, 207, 205},
+ {204, 206, 204, 206},
+ },
+ {
+ {209, 207, 208, 206},
+ {206, 208, 205, 207},
+ {208, 206, 208, 206},
+ {205, 207, 205, 207},
+ },
+ {
+ {210, 208, 209, 207},
+ {207, 209, 206, 208},
+ {209, 207, 209, 207},
+ {206, 208, 206, 208},
+ },
+ {
+ {211, 209, 210, 208},
+ {208, 210, 207, 209},
+ {210, 208, 210, 208},
+ {207, 209, 207, 209},
+ },
+ {
+ {212, 210, 211, 209},
+ {209, 211, 208, 210},
+ {211, 209, 211, 209},
+ {208, 210, 208, 210},
+ },
+ {
+ {213, 211, 212, 210},
+ {210, 212, 209, 211},
+ {212, 210, 212, 210},
+ {209, 211, 209, 211},
+ },
+ {
+ {214, 212, 213, 211},
+ {211, 213, 210, 212},
+ {213, 211, 213, 211},
+ {210, 212, 210, 212},
+ },
+ {
+ {215, 213, 214, 212},
+ {212, 214, 211, 213},
+ {214, 212, 214, 212},
+ {211, 213, 211, 213},
+ },
+ {
+ {216, 214, 215, 213},
+ {213, 215, 212, 214},
+ {215, 213, 215, 213},
+ {212, 214, 212, 214},
+ },
+ {
+ {217, 215, 216, 214},
+ {214, 216, 213, 215},
+ {216, 214, 216, 214},
+ {213, 215, 213, 215},
+ },
+ {
+ {218, 216, 217, 215},
+ {215, 217, 214, 216},
+ {217, 215, 217, 215},
+ {214, 216, 214, 216},
+ },
+ {
+ {219, 217, 218, 216},
+ {216, 218, 215, 217},
+ {218, 216, 218, 216},
+ {215, 217, 215, 217},
+ },
+ {
+ {220, 218, 219, 217},
+ {217, 219, 216, 218},
+ {219, 217, 219, 217},
+ {216, 218, 216, 218},
+ },
+ {
+ {221, 219, 220, 218},
+ {218, 220, 217, 219},
+ {220, 218, 220, 218},
+ {217, 219, 217, 219},
+ },
+ {
+ {222, 220, 221, 219},
+ {219, 221, 218, 220},
+ {221, 219, 221, 219},
+ {218, 220, 218, 220},
+ },
+ {
+ {223, 221, 222, 220},
+ {220, 222, 219, 221},
+ {222, 220, 222, 220},
+ {219, 221, 219, 221},
+ },
+ {
+ {224, 222, 223, 221},
+ {221, 223, 220, 222},
+ {223, 221, 223, 221},
+ {220, 222, 220, 222},
+ },
+ {
+ {225, 223, 224, 222},
+ {222, 224, 221, 223},
+ {224, 222, 224, 222},
+ {221, 223, 221, 223},
+ },
+ {
+ {226, 224, 225, 223},
+ {223, 225, 222, 224},
+ {225, 223, 225, 223},
+ {222, 224, 222, 224},
+ },
+ {
+ {227, 225, 226, 224},
+ {224, 226, 223, 225},
+ {226, 224, 226, 224},
+ {223, 225, 223, 225},
+ },
+ {
+ {228, 226, 227, 225},
+ {225, 227, 224, 226},
+ {227, 225, 227, 225},
+ {224, 226, 224, 226},
+ },
+ {
+ {229, 227, 228, 226},
+ {226, 228, 225, 227},
+ {228, 226, 228, 226},
+ {225, 227, 225, 227},
+ },
+ {
+ {230, 228, 229, 227},
+ {227, 229, 226, 228},
+ {229, 227, 229, 227},
+ {226, 228, 226, 228},
+ },
+ {
+ {231, 229, 230, 228},
+ {228, 230, 227, 229},
+ {230, 228, 230, 228},
+ {227, 229, 227, 229},
+ },
+ {
+ {232, 230, 231, 229},
+ {229, 231, 228, 230},
+ {231, 229, 231, 229},
+ {228, 230, 228, 230},
+ },
+ {
+ {233, 231, 232, 230},
+ {230, 232, 229, 231},
+ {232, 230, 232, 230},
+ {229, 231, 229, 231},
+ },
+ {
+ {234, 232, 233, 231},
+ {231, 233, 230, 232},
+ {233, 231, 233, 231},
+ {230, 232, 230, 232},
+ },
+ {
+ {235, 233, 234, 232},
+ {232, 234, 231, 233},
+ {234, 232, 234, 232},
+ {231, 233, 231, 233},
+ },
+ {
+ {236, 234, 235, 233},
+ {233, 235, 232, 234},
+ {235, 233, 235, 233},
+ {232, 234, 232, 234},
+ },
+ {
+ {237, 235, 236, 234},
+ {234, 236, 233, 235},
+ {236, 234, 236, 234},
+ {233, 235, 233, 235},
+ },
+ {
+ {238, 236, 237, 235},
+ {235, 237, 234, 236},
+ {237, 235, 237, 235},
+ {234, 236, 234, 236},
+ },
+ {
+ {239, 237, 238, 236},
+ {236, 238, 235, 237},
+ {238, 236, 238, 236},
+ {235, 237, 235, 237},
+ },
+ {
+ {240, 238, 239, 237},
+ {237, 239, 236, 238},
+ {239, 237, 239, 237},
+ {236, 238, 236, 238},
+ },
+ {
+ {241, 239, 240, 238},
+ {238, 240, 237, 239},
+ {240, 238, 240, 238},
+ {237, 239, 237, 239},
+ },
+ {
+ {242, 240, 241, 239},
+ {239, 241, 238, 240},
+ {241, 239, 241, 239},
+ {238, 240, 238, 240},
+ },
+ {
+ {243, 241, 242, 240},
+ {240, 242, 239, 241},
+ {242, 240, 242, 240},
+ {239, 241, 239, 241},
+ },
+ {
+ {244, 242, 243, 241},
+ {241, 243, 240, 242},
+ {243, 241, 243, 241},
+ {240, 242, 240, 242},
+ },
+ {
+ {245, 243, 244, 242},
+ {242, 244, 241, 243},
+ {244, 242, 244, 242},
+ {241, 243, 241, 243},
+ },
+ {
+ {246, 244, 245, 243},
+ {243, 245, 242, 244},
+ {245, 243, 245, 243},
+ {242, 244, 242, 244},
+ },
+ {
+ {247, 245, 246, 244},
+ {244, 246, 243, 245},
+ {246, 244, 246, 244},
+ {243, 245, 243, 245},
+ },
+ {
+ {248, 246, 247, 245},
+ {245, 247, 244, 246},
+ {247, 245, 247, 245},
+ {244, 246, 244, 246},
+ },
+ {
+ {249, 247, 248, 246},
+ {246, 248, 245, 247},
+ {248, 246, 248, 246},
+ {245, 247, 245, 247},
+ },
+ {
+ {250, 248, 249, 247},
+ {247, 249, 246, 248},
+ {249, 247, 249, 247},
+ {246, 248, 246, 248},
+ },
+ {
+ {251, 249, 250, 248},
+ {248, 250, 247, 249},
+ {250, 248, 250, 248},
+ {247, 249, 247, 249},
+ },
+ {
+ {252, 250, 251, 249},
+ {249, 251, 248, 250},
+ {251, 249, 251, 249},
+ {248, 250, 248, 250},
+ },
+ {
+ {253, 251, 252, 250},
+ {250, 252, 249, 251},
+ {252, 250, 252, 250},
+ {249, 251, 249, 251},
+ },
+ {
+ {254, 252, 253, 251},
+ {251, 253, 250, 252},
+ {253, 251, 253, 251},
+ {250, 252, 250, 252},
+ },
+ {
+ {255, 253, 254, 252},
+ {252, 254, 251, 253},
+ {254, 252, 254, 252},
+ {251, 253, 251, 253},
+ },
+ {
+ {255, 254, 255, 253},
+ {253, 255, 252, 254},
+ {255, 253, 255, 253},
+ {252, 254, 252, 254},
+ },
+ {
+ {255, 255, 255, 254},
+ {254, 255, 253, 255},
+ {255, 254, 255, 254},
+ {253, 255, 253, 255},
+ },
+ {
+ {255, 255, 255, 255},
+ {255, 255, 254, 255},
+ {255, 255, 255, 255},
+ {254, 255, 254, 255},
+ },
+};
+
+
+
+
+static const uint8_t dithersub_g2x2[256][2][2] =
+{
+ {
+ {0, 0},
+ {0, 0},
+ },
+ {
+ {0, 0},
+ {0, 0},
+ },
+ {
+ {4, 2},
+ {1, 3},
+ },
+ {
+ {5, 3},
+ {2, 4},
+ },
+ {
+ {6, 4},
+ {3, 5},
+ },
+ {
+ {7, 5},
+ {4, 6},
+ },
+ {
+ {8, 6},
+ {5, 7},
+ },
+ {
+ {9, 7},
+ {6, 8},
+ },
+ {
+ {10, 8},
+ {7, 9},
+ },
+ {
+ {11, 9},
+ {8, 10},
+ },
+ {
+ {12, 10},
+ {9, 11},
+ },
+ {
+ {13, 11},
+ {10, 12},
+ },
+ {
+ {14, 12},
+ {11, 13},
+ },
+ {
+ {15, 13},
+ {12, 14},
+ },
+ {
+ {16, 14},
+ {13, 15},
+ },
+ {
+ {17, 15},
+ {14, 16},
+ },
+ {
+ {18, 16},
+ {15, 17},
+ },
+ {
+ {19, 17},
+ {16, 18},
+ },
+ {
+ {20, 18},
+ {17, 19},
+ },
+ {
+ {21, 19},
+ {18, 20},
+ },
+ {
+ {22, 20},
+ {19, 21},
+ },
+ {
+ {23, 21},
+ {20, 22},
+ },
+ {
+ {24, 22},
+ {21, 23},
+ },
+ {
+ {25, 23},
+ {22, 24},
+ },
+ {
+ {26, 24},
+ {23, 25},
+ },
+ {
+ {27, 25},
+ {24, 26},
+ },
+ {
+ {28, 26},
+ {25, 27},
+ },
+ {
+ {29, 27},
+ {26, 28},
+ },
+ {
+ {30, 28},
+ {27, 29},
+ },
+ {
+ {31, 29},
+ {28, 30},
+ },
+ {
+ {32, 30},
+ {29, 31},
+ },
+ {
+ {33, 31},
+ {30, 32},
+ },
+ {
+ {34, 32},
+ {31, 33},
+ },
+ {
+ {35, 33},
+ {32, 34},
+ },
+ {
+ {36, 34},
+ {33, 35},
+ },
+ {
+ {37, 35},
+ {34, 36},
+ },
+ {
+ {38, 36},
+ {35, 37},
+ },
+ {
+ {39, 37},
+ {36, 38},
+ },
+ {
+ {40, 38},
+ {37, 39},
+ },
+ {
+ {41, 39},
+ {38, 40},
+ },
+ {
+ {42, 40},
+ {39, 41},
+ },
+ {
+ {43, 41},
+ {40, 42},
+ },
+ {
+ {44, 42},
+ {41, 43},
+ },
+ {
+ {45, 43},
+ {42, 44},
+ },
+ {
+ {46, 44},
+ {43, 45},
+ },
+ {
+ {47, 45},
+ {44, 46},
+ },
+ {
+ {48, 46},
+ {45, 47},
+ },
+ {
+ {49, 47},
+ {46, 48},
+ },
+ {
+ {50, 48},
+ {47, 49},
+ },
+ {
+ {51, 49},
+ {48, 50},
+ },
+ {
+ {52, 50},
+ {49, 51},
+ },
+ {
+ {53, 51},
+ {50, 52},
+ },
+ {
+ {54, 52},
+ {51, 53},
+ },
+ {
+ {55, 53},
+ {52, 54},
+ },
+ {
+ {56, 54},
+ {53, 55},
+ },
+ {
+ {57, 55},
+ {54, 56},
+ },
+ {
+ {58, 56},
+ {55, 57},
+ },
+ {
+ {59, 57},
+ {56, 58},
+ },
+ {
+ {60, 58},
+ {57, 59},
+ },
+ {
+ {61, 59},
+ {58, 60},
+ },
+ {
+ {62, 60},
+ {59, 61},
+ },
+ {
+ {63, 61},
+ {60, 62},
+ },
+ {
+ {64, 62},
+ {61, 63},
+ },
+ {
+ {65, 63},
+ {62, 64},
+ },
+ {
+ {66, 64},
+ {63, 65},
+ },
+ {
+ {67, 65},
+ {64, 66},
+ },
+ {
+ {68, 66},
+ {65, 67},
+ },
+ {
+ {69, 67},
+ {66, 68},
+ },
+ {
+ {70, 68},
+ {67, 69},
+ },
+ {
+ {71, 69},
+ {68, 70},
+ },
+ {
+ {72, 70},
+ {69, 71},
+ },
+ {
+ {73, 71},
+ {70, 72},
+ },
+ {
+ {74, 72},
+ {71, 73},
+ },
+ {
+ {75, 73},
+ {72, 74},
+ },
+ {
+ {76, 74},
+ {73, 75},
+ },
+ {
+ {77, 75},
+ {74, 76},
+ },
+ {
+ {78, 76},
+ {75, 77},
+ },
+ {
+ {79, 77},
+ {76, 78},
+ },
+ {
+ {80, 78},
+ {77, 79},
+ },
+ {
+ {81, 79},
+ {78, 80},
+ },
+ {
+ {82, 80},
+ {79, 81},
+ },
+ {
+ {83, 81},
+ {80, 82},
+ },
+ {
+ {84, 82},
+ {81, 83},
+ },
+ {
+ {85, 83},
+ {82, 84},
+ },
+ {
+ {86, 84},
+ {83, 85},
+ },
+ {
+ {87, 85},
+ {84, 86},
+ },
+ {
+ {88, 86},
+ {85, 87},
+ },
+ {
+ {89, 87},
+ {86, 88},
+ },
+ {
+ {90, 88},
+ {87, 89},
+ },
+ {
+ {91, 89},
+ {88, 90},
+ },
+ {
+ {92, 90},
+ {89, 91},
+ },
+ {
+ {93, 91},
+ {90, 92},
+ },
+ {
+ {94, 92},
+ {91, 93},
+ },
+ {
+ {95, 93},
+ {92, 94},
+ },
+ {
+ {96, 94},
+ {93, 95},
+ },
+ {
+ {97, 95},
+ {94, 96},
+ },
+ {
+ {98, 96},
+ {95, 97},
+ },
+ {
+ {99, 97},
+ {96, 98},
+ },
+ {
+ {100, 98},
+ {97, 99},
+ },
+ {
+ {101, 99},
+ {98, 100},
+ },
+ {
+ {102, 100},
+ {99, 101},
+ },
+ {
+ {103, 101},
+ {100, 102},
+ },
+ {
+ {104, 102},
+ {101, 103},
+ },
+ {
+ {105, 103},
+ {102, 104},
+ },
+ {
+ {106, 104},
+ {103, 105},
+ },
+ {
+ {107, 105},
+ {104, 106},
+ },
+ {
+ {108, 106},
+ {105, 107},
+ },
+ {
+ {109, 107},
+ {106, 108},
+ },
+ {
+ {110, 108},
+ {107, 109},
+ },
+ {
+ {111, 109},
+ {108, 110},
+ },
+ {
+ {112, 110},
+ {109, 111},
+ },
+ {
+ {113, 111},
+ {110, 112},
+ },
+ {
+ {114, 112},
+ {111, 113},
+ },
+ {
+ {115, 113},
+ {112, 114},
+ },
+ {
+ {116, 114},
+ {113, 115},
+ },
+ {
+ {117, 115},
+ {114, 116},
+ },
+ {
+ {118, 116},
+ {115, 117},
+ },
+ {
+ {119, 117},
+ {116, 118},
+ },
+ {
+ {120, 118},
+ {117, 119},
+ },
+ {
+ {121, 119},
+ {118, 120},
+ },
+ {
+ {122, 120},
+ {119, 121},
+ },
+ {
+ {123, 121},
+ {120, 122},
+ },
+ {
+ {124, 122},
+ {121, 123},
+ },
+ {
+ {125, 123},
+ {122, 124},
+ },
+ {
+ {126, 124},
+ {123, 125},
+ },
+ {
+ {127, 125},
+ {124, 126},
+ },
+ {
+ {128, 126},
+ {125, 127},
+ },
+ {
+ {129, 127},
+ {126, 128},
+ },
+ {
+ {130, 128},
+ {127, 129},
+ },
+ {
+ {131, 129},
+ {128, 130},
+ },
+ {
+ {132, 130},
+ {129, 131},
+ },
+ {
+ {133, 131},
+ {130, 132},
+ },
+ {
+ {134, 132},
+ {131, 133},
+ },
+ {
+ {135, 133},
+ {132, 134},
+ },
+ {
+ {136, 134},
+ {133, 135},
+ },
+ {
+ {137, 135},
+ {134, 136},
+ },
+ {
+ {138, 136},
+ {135, 137},
+ },
+ {
+ {139, 137},
+ {136, 138},
+ },
+ {
+ {140, 138},
+ {137, 139},
+ },
+ {
+ {141, 139},
+ {138, 140},
+ },
+ {
+ {142, 140},
+ {139, 141},
+ },
+ {
+ {143, 141},
+ {140, 142},
+ },
+ {
+ {144, 142},
+ {141, 143},
+ },
+ {
+ {145, 143},
+ {142, 144},
+ },
+ {
+ {146, 144},
+ {143, 145},
+ },
+ {
+ {147, 145},
+ {144, 146},
+ },
+ {
+ {148, 146},
+ {145, 147},
+ },
+ {
+ {149, 147},
+ {146, 148},
+ },
+ {
+ {150, 148},
+ {147, 149},
+ },
+ {
+ {151, 149},
+ {148, 150},
+ },
+ {
+ {152, 150},
+ {149, 151},
+ },
+ {
+ {153, 151},
+ {150, 152},
+ },
+ {
+ {154, 152},
+ {151, 153},
+ },
+ {
+ {155, 153},
+ {152, 154},
+ },
+ {
+ {156, 154},
+ {153, 155},
+ },
+ {
+ {157, 155},
+ {154, 156},
+ },
+ {
+ {158, 156},
+ {155, 157},
+ },
+ {
+ {159, 157},
+ {156, 158},
+ },
+ {
+ {160, 158},
+ {157, 159},
+ },
+ {
+ {161, 159},
+ {158, 160},
+ },
+ {
+ {162, 160},
+ {159, 161},
+ },
+ {
+ {163, 161},
+ {160, 162},
+ },
+ {
+ {164, 162},
+ {161, 163},
+ },
+ {
+ {165, 163},
+ {162, 164},
+ },
+ {
+ {166, 164},
+ {163, 165},
+ },
+ {
+ {167, 165},
+ {164, 166},
+ },
+ {
+ {168, 166},
+ {165, 167},
+ },
+ {
+ {169, 167},
+ {166, 168},
+ },
+ {
+ {170, 168},
+ {167, 169},
+ },
+ {
+ {171, 169},
+ {168, 170},
+ },
+ {
+ {172, 170},
+ {169, 171},
+ },
+ {
+ {173, 171},
+ {170, 172},
+ },
+ {
+ {174, 172},
+ {171, 173},
+ },
+ {
+ {175, 173},
+ {172, 174},
+ },
+ {
+ {176, 174},
+ {173, 175},
+ },
+ {
+ {177, 175},
+ {174, 176},
+ },
+ {
+ {178, 176},
+ {175, 177},
+ },
+ {
+ {179, 177},
+ {176, 178},
+ },
+ {
+ {180, 178},
+ {177, 179},
+ },
+ {
+ {181, 179},
+ {178, 180},
+ },
+ {
+ {182, 180},
+ {179, 181},
+ },
+ {
+ {183, 181},
+ {180, 182},
+ },
+ {
+ {184, 182},
+ {181, 183},
+ },
+ {
+ {185, 183},
+ {182, 184},
+ },
+ {
+ {186, 184},
+ {183, 185},
+ },
+ {
+ {187, 185},
+ {184, 186},
+ },
+ {
+ {188, 186},
+ {185, 187},
+ },
+ {
+ {189, 187},
+ {186, 188},
+ },
+ {
+ {190, 188},
+ {187, 189},
+ },
+ {
+ {191, 189},
+ {188, 190},
+ },
+ {
+ {192, 190},
+ {189, 191},
+ },
+ {
+ {193, 191},
+ {190, 192},
+ },
+ {
+ {194, 192},
+ {191, 193},
+ },
+ {
+ {195, 193},
+ {192, 194},
+ },
+ {
+ {196, 194},
+ {193, 195},
+ },
+ {
+ {197, 195},
+ {194, 196},
+ },
+ {
+ {198, 196},
+ {195, 197},
+ },
+ {
+ {199, 197},
+ {196, 198},
+ },
+ {
+ {200, 198},
+ {197, 199},
+ },
+ {
+ {201, 199},
+ {198, 200},
+ },
+ {
+ {202, 200},
+ {199, 201},
+ },
+ {
+ {203, 201},
+ {200, 202},
+ },
+ {
+ {204, 202},
+ {201, 203},
+ },
+ {
+ {205, 203},
+ {202, 204},
+ },
+ {
+ {206, 204},
+ {203, 205},
+ },
+ {
+ {207, 205},
+ {204, 206},
+ },
+ {
+ {208, 206},
+ {205, 207},
+ },
+ {
+ {209, 207},
+ {206, 208},
+ },
+ {
+ {210, 208},
+ {207, 209},
+ },
+ {
+ {211, 209},
+ {208, 210},
+ },
+ {
+ {212, 210},
+ {209, 211},
+ },
+ {
+ {213, 211},
+ {210, 212},
+ },
+ {
+ {214, 212},
+ {211, 213},
+ },
+ {
+ {215, 213},
+ {212, 214},
+ },
+ {
+ {216, 214},
+ {213, 215},
+ },
+ {
+ {217, 215},
+ {214, 216},
+ },
+ {
+ {218, 216},
+ {215, 217},
+ },
+ {
+ {219, 217},
+ {216, 218},
+ },
+ {
+ {220, 218},
+ {217, 219},
+ },
+ {
+ {221, 219},
+ {218, 220},
+ },
+ {
+ {222, 220},
+ {219, 221},
+ },
+ {
+ {223, 221},
+ {220, 222},
+ },
+ {
+ {224, 222},
+ {221, 223},
+ },
+ {
+ {225, 223},
+ {222, 224},
+ },
+ {
+ {226, 224},
+ {223, 225},
+ },
+ {
+ {227, 225},
+ {224, 226},
+ },
+ {
+ {228, 226},
+ {225, 227},
+ },
+ {
+ {229, 227},
+ {226, 228},
+ },
+ {
+ {230, 228},
+ {227, 229},
+ },
+ {
+ {231, 229},
+ {228, 230},
+ },
+ {
+ {232, 230},
+ {229, 231},
+ },
+ {
+ {233, 231},
+ {230, 232},
+ },
+ {
+ {234, 232},
+ {231, 233},
+ },
+ {
+ {235, 233},
+ {232, 234},
+ },
+ {
+ {236, 234},
+ {233, 235},
+ },
+ {
+ {237, 235},
+ {234, 236},
+ },
+ {
+ {238, 236},
+ {235, 237},
+ },
+ {
+ {239, 237},
+ {236, 238},
+ },
+ {
+ {240, 238},
+ {237, 239},
+ },
+ {
+ {241, 239},
+ {238, 240},
+ },
+ {
+ {242, 240},
+ {239, 241},
+ },
+ {
+ {243, 241},
+ {240, 242},
+ },
+ {
+ {244, 242},
+ {241, 243},
+ },
+ {
+ {245, 243},
+ {242, 244},
+ },
+ {
+ {246, 244},
+ {243, 245},
+ },
+ {
+ {247, 245},
+ {244, 246},
+ },
+ {
+ {248, 246},
+ {245, 247},
+ },
+ {
+ {249, 247},
+ {246, 248},
+ },
+ {
+ {250, 248},
+ {247, 249},
+ },
+ {
+ {251, 249},
+ {248, 250},
+ },
+ {
+ {252, 250},
+ {249, 251},
+ },
+ {
+ {253, 251},
+ {250, 252},
+ },
+ {
+ {254, 252},
+ {251, 253},
+ },
+ {
+ {255, 253},
+ {252, 254},
+ },
+ {
+ {255, 254},
+ {253, 255},
+ },
+ {
+ {255, 255},
+ {254, 255},
+ },
+};
+
+
+static const uint8_t dithersub_rb2x2[256][2][2] =
+{
+ {
+ {0, 0},
+ {0, 0},
+ },
+ {
+ {0, 0},
+ {0, 0},
+ },
+ {
+ {0, 0},
+ {0, 0},
+ },
+ {
+ {0, 0},
+ {0, 0},
+ },
+ {
+ {8, 4},
+ {2, 6},
+ },
+ {
+ {9, 5},
+ {3, 7},
+ },
+ {
+ {10, 6},
+ {4, 8},
+ },
+ {
+ {11, 7},
+ {5, 9},
+ },
+ {
+ {12, 8},
+ {6, 10},
+ },
+ {
+ {13, 9},
+ {7, 11},
+ },
+ {
+ {14, 10},
+ {8, 12},
+ },
+ {
+ {15, 11},
+ {9, 13},
+ },
+ {
+ {16, 12},
+ {10, 14},
+ },
+ {
+ {17, 13},
+ {11, 15},
+ },
+ {
+ {18, 14},
+ {12, 16},
+ },
+ {
+ {19, 15},
+ {13, 17},
+ },
+ {
+ {20, 16},
+ {14, 18},
+ },
+ {
+ {21, 17},
+ {15, 19},
+ },
+ {
+ {22, 18},
+ {16, 20},
+ },
+ {
+ {23, 19},
+ {17, 21},
+ },
+ {
+ {24, 20},
+ {18, 22},
+ },
+ {
+ {25, 21},
+ {19, 23},
+ },
+ {
+ {26, 22},
+ {20, 24},
+ },
+ {
+ {27, 23},
+ {21, 25},
+ },
+ {
+ {28, 24},
+ {22, 26},
+ },
+ {
+ {29, 25},
+ {23, 27},
+ },
+ {
+ {30, 26},
+ {24, 28},
+ },
+ {
+ {31, 27},
+ {25, 29},
+ },
+ {
+ {32, 28},
+ {26, 30},
+ },
+ {
+ {33, 29},
+ {27, 31},
+ },
+ {
+ {34, 30},
+ {28, 32},
+ },
+ {
+ {35, 31},
+ {29, 33},
+ },
+ {
+ {36, 32},
+ {30, 34},
+ },
+ {
+ {37, 33},
+ {31, 35},
+ },
+ {
+ {38, 34},
+ {32, 36},
+ },
+ {
+ {39, 35},
+ {33, 37},
+ },
+ {
+ {40, 36},
+ {34, 38},
+ },
+ {
+ {41, 37},
+ {35, 39},
+ },
+ {
+ {42, 38},
+ {36, 40},
+ },
+ {
+ {43, 39},
+ {37, 41},
+ },
+ {
+ {44, 40},
+ {38, 42},
+ },
+ {
+ {45, 41},
+ {39, 43},
+ },
+ {
+ {46, 42},
+ {40, 44},
+ },
+ {
+ {47, 43},
+ {41, 45},
+ },
+ {
+ {48, 44},
+ {42, 46},
+ },
+ {
+ {49, 45},
+ {43, 47},
+ },
+ {
+ {50, 46},
+ {44, 48},
+ },
+ {
+ {51, 47},
+ {45, 49},
+ },
+ {
+ {52, 48},
+ {46, 50},
+ },
+ {
+ {53, 49},
+ {47, 51},
+ },
+ {
+ {54, 50},
+ {48, 52},
+ },
+ {
+ {55, 51},
+ {49, 53},
+ },
+ {
+ {56, 52},
+ {50, 54},
+ },
+ {
+ {57, 53},
+ {51, 55},
+ },
+ {
+ {58, 54},
+ {52, 56},
+ },
+ {
+ {59, 55},
+ {53, 57},
+ },
+ {
+ {60, 56},
+ {54, 58},
+ },
+ {
+ {61, 57},
+ {55, 59},
+ },
+ {
+ {62, 58},
+ {56, 60},
+ },
+ {
+ {63, 59},
+ {57, 61},
+ },
+ {
+ {64, 60},
+ {58, 62},
+ },
+ {
+ {65, 61},
+ {59, 63},
+ },
+ {
+ {66, 62},
+ {60, 64},
+ },
+ {
+ {67, 63},
+ {61, 65},
+ },
+ {
+ {68, 64},
+ {62, 66},
+ },
+ {
+ {69, 65},
+ {63, 67},
+ },
+ {
+ {70, 66},
+ {64, 68},
+ },
+ {
+ {71, 67},
+ {65, 69},
+ },
+ {
+ {72, 68},
+ {66, 70},
+ },
+ {
+ {73, 69},
+ {67, 71},
+ },
+ {
+ {74, 70},
+ {68, 72},
+ },
+ {
+ {75, 71},
+ {69, 73},
+ },
+ {
+ {76, 72},
+ {70, 74},
+ },
+ {
+ {77, 73},
+ {71, 75},
+ },
+ {
+ {78, 74},
+ {72, 76},
+ },
+ {
+ {79, 75},
+ {73, 77},
+ },
+ {
+ {80, 76},
+ {74, 78},
+ },
+ {
+ {81, 77},
+ {75, 79},
+ },
+ {
+ {82, 78},
+ {76, 80},
+ },
+ {
+ {83, 79},
+ {77, 81},
+ },
+ {
+ {84, 80},
+ {78, 82},
+ },
+ {
+ {85, 81},
+ {79, 83},
+ },
+ {
+ {86, 82},
+ {80, 84},
+ },
+ {
+ {87, 83},
+ {81, 85},
+ },
+ {
+ {88, 84},
+ {82, 86},
+ },
+ {
+ {89, 85},
+ {83, 87},
+ },
+ {
+ {90, 86},
+ {84, 88},
+ },
+ {
+ {91, 87},
+ {85, 89},
+ },
+ {
+ {92, 88},
+ {86, 90},
+ },
+ {
+ {93, 89},
+ {87, 91},
+ },
+ {
+ {94, 90},
+ {88, 92},
+ },
+ {
+ {95, 91},
+ {89, 93},
+ },
+ {
+ {96, 92},
+ {90, 94},
+ },
+ {
+ {97, 93},
+ {91, 95},
+ },
+ {
+ {98, 94},
+ {92, 96},
+ },
+ {
+ {99, 95},
+ {93, 97},
+ },
+ {
+ {100, 96},
+ {94, 98},
+ },
+ {
+ {101, 97},
+ {95, 99},
+ },
+ {
+ {102, 98},
+ {96, 100},
+ },
+ {
+ {103, 99},
+ {97, 101},
+ },
+ {
+ {104, 100},
+ {98, 102},
+ },
+ {
+ {105, 101},
+ {99, 103},
+ },
+ {
+ {106, 102},
+ {100, 104},
+ },
+ {
+ {107, 103},
+ {101, 105},
+ },
+ {
+ {108, 104},
+ {102, 106},
+ },
+ {
+ {109, 105},
+ {103, 107},
+ },
+ {
+ {110, 106},
+ {104, 108},
+ },
+ {
+ {111, 107},
+ {105, 109},
+ },
+ {
+ {112, 108},
+ {106, 110},
+ },
+ {
+ {113, 109},
+ {107, 111},
+ },
+ {
+ {114, 110},
+ {108, 112},
+ },
+ {
+ {115, 111},
+ {109, 113},
+ },
+ {
+ {116, 112},
+ {110, 114},
+ },
+ {
+ {117, 113},
+ {111, 115},
+ },
+ {
+ {118, 114},
+ {112, 116},
+ },
+ {
+ {119, 115},
+ {113, 117},
+ },
+ {
+ {120, 116},
+ {114, 118},
+ },
+ {
+ {121, 117},
+ {115, 119},
+ },
+ {
+ {122, 118},
+ {116, 120},
+ },
+ {
+ {123, 119},
+ {117, 121},
+ },
+ {
+ {124, 120},
+ {118, 122},
+ },
+ {
+ {125, 121},
+ {119, 123},
+ },
+ {
+ {126, 122},
+ {120, 124},
+ },
+ {
+ {127, 123},
+ {121, 125},
+ },
+ {
+ {128, 124},
+ {122, 126},
+ },
+ {
+ {129, 125},
+ {123, 127},
+ },
+ {
+ {130, 126},
+ {124, 128},
+ },
+ {
+ {131, 127},
+ {125, 129},
+ },
+ {
+ {132, 128},
+ {126, 130},
+ },
+ {
+ {133, 129},
+ {127, 131},
+ },
+ {
+ {134, 130},
+ {128, 132},
+ },
+ {
+ {135, 131},
+ {129, 133},
+ },
+ {
+ {136, 132},
+ {130, 134},
+ },
+ {
+ {137, 133},
+ {131, 135},
+ },
+ {
+ {138, 134},
+ {132, 136},
+ },
+ {
+ {139, 135},
+ {133, 137},
+ },
+ {
+ {140, 136},
+ {134, 138},
+ },
+ {
+ {141, 137},
+ {135, 139},
+ },
+ {
+ {142, 138},
+ {136, 140},
+ },
+ {
+ {143, 139},
+ {137, 141},
+ },
+ {
+ {144, 140},
+ {138, 142},
+ },
+ {
+ {145, 141},
+ {139, 143},
+ },
+ {
+ {146, 142},
+ {140, 144},
+ },
+ {
+ {147, 143},
+ {141, 145},
+ },
+ {
+ {148, 144},
+ {142, 146},
+ },
+ {
+ {149, 145},
+ {143, 147},
+ },
+ {
+ {150, 146},
+ {144, 148},
+ },
+ {
+ {151, 147},
+ {145, 149},
+ },
+ {
+ {152, 148},
+ {146, 150},
+ },
+ {
+ {153, 149},
+ {147, 151},
+ },
+ {
+ {154, 150},
+ {148, 152},
+ },
+ {
+ {155, 151},
+ {149, 153},
+ },
+ {
+ {156, 152},
+ {150, 154},
+ },
+ {
+ {157, 153},
+ {151, 155},
+ },
+ {
+ {158, 154},
+ {152, 156},
+ },
+ {
+ {159, 155},
+ {153, 157},
+ },
+ {
+ {160, 156},
+ {154, 158},
+ },
+ {
+ {161, 157},
+ {155, 159},
+ },
+ {
+ {162, 158},
+ {156, 160},
+ },
+ {
+ {163, 159},
+ {157, 161},
+ },
+ {
+ {164, 160},
+ {158, 162},
+ },
+ {
+ {165, 161},
+ {159, 163},
+ },
+ {
+ {166, 162},
+ {160, 164},
+ },
+ {
+ {167, 163},
+ {161, 165},
+ },
+ {
+ {168, 164},
+ {162, 166},
+ },
+ {
+ {169, 165},
+ {163, 167},
+ },
+ {
+ {170, 166},
+ {164, 168},
+ },
+ {
+ {171, 167},
+ {165, 169},
+ },
+ {
+ {172, 168},
+ {166, 170},
+ },
+ {
+ {173, 169},
+ {167, 171},
+ },
+ {
+ {174, 170},
+ {168, 172},
+ },
+ {
+ {175, 171},
+ {169, 173},
+ },
+ {
+ {176, 172},
+ {170, 174},
+ },
+ {
+ {177, 173},
+ {171, 175},
+ },
+ {
+ {178, 174},
+ {172, 176},
+ },
+ {
+ {179, 175},
+ {173, 177},
+ },
+ {
+ {180, 176},
+ {174, 178},
+ },
+ {
+ {181, 177},
+ {175, 179},
+ },
+ {
+ {182, 178},
+ {176, 180},
+ },
+ {
+ {183, 179},
+ {177, 181},
+ },
+ {
+ {184, 180},
+ {178, 182},
+ },
+ {
+ {185, 181},
+ {179, 183},
+ },
+ {
+ {186, 182},
+ {180, 184},
+ },
+ {
+ {187, 183},
+ {181, 185},
+ },
+ {
+ {188, 184},
+ {182, 186},
+ },
+ {
+ {189, 185},
+ {183, 187},
+ },
+ {
+ {190, 186},
+ {184, 188},
+ },
+ {
+ {191, 187},
+ {185, 189},
+ },
+ {
+ {192, 188},
+ {186, 190},
+ },
+ {
+ {193, 189},
+ {187, 191},
+ },
+ {
+ {194, 190},
+ {188, 192},
+ },
+ {
+ {195, 191},
+ {189, 193},
+ },
+ {
+ {196, 192},
+ {190, 194},
+ },
+ {
+ {197, 193},
+ {191, 195},
+ },
+ {
+ {198, 194},
+ {192, 196},
+ },
+ {
+ {199, 195},
+ {193, 197},
+ },
+ {
+ {200, 196},
+ {194, 198},
+ },
+ {
+ {201, 197},
+ {195, 199},
+ },
+ {
+ {202, 198},
+ {196, 200},
+ },
+ {
+ {203, 199},
+ {197, 201},
+ },
+ {
+ {204, 200},
+ {198, 202},
+ },
+ {
+ {205, 201},
+ {199, 203},
+ },
+ {
+ {206, 202},
+ {200, 204},
+ },
+ {
+ {207, 203},
+ {201, 205},
+ },
+ {
+ {208, 204},
+ {202, 206},
+ },
+ {
+ {209, 205},
+ {203, 207},
+ },
+ {
+ {210, 206},
+ {204, 208},
+ },
+ {
+ {211, 207},
+ {205, 209},
+ },
+ {
+ {212, 208},
+ {206, 210},
+ },
+ {
+ {213, 209},
+ {207, 211},
+ },
+ {
+ {214, 210},
+ {208, 212},
+ },
+ {
+ {215, 211},
+ {209, 213},
+ },
+ {
+ {216, 212},
+ {210, 214},
+ },
+ {
+ {217, 213},
+ {211, 215},
+ },
+ {
+ {218, 214},
+ {212, 216},
+ },
+ {
+ {219, 215},
+ {213, 217},
+ },
+ {
+ {220, 216},
+ {214, 218},
+ },
+ {
+ {221, 217},
+ {215, 219},
+ },
+ {
+ {222, 218},
+ {216, 220},
+ },
+ {
+ {223, 219},
+ {217, 221},
+ },
+ {
+ {224, 220},
+ {218, 222},
+ },
+ {
+ {225, 221},
+ {219, 223},
+ },
+ {
+ {226, 222},
+ {220, 224},
+ },
+ {
+ {227, 223},
+ {221, 225},
+ },
+ {
+ {228, 224},
+ {222, 226},
+ },
+ {
+ {229, 225},
+ {223, 227},
+ },
+ {
+ {230, 226},
+ {224, 228},
+ },
+ {
+ {231, 227},
+ {225, 229},
+ },
+ {
+ {232, 228},
+ {226, 230},
+ },
+ {
+ {233, 229},
+ {227, 231},
+ },
+ {
+ {234, 230},
+ {228, 232},
+ },
+ {
+ {235, 231},
+ {229, 233},
+ },
+ {
+ {236, 232},
+ {230, 234},
+ },
+ {
+ {237, 233},
+ {231, 235},
+ },
+ {
+ {238, 234},
+ {232, 236},
+ },
+ {
+ {239, 235},
+ {233, 237},
+ },
+ {
+ {240, 236},
+ {234, 238},
+ },
+ {
+ {241, 237},
+ {235, 239},
+ },
+ {
+ {242, 238},
+ {236, 240},
+ },
+ {
+ {243, 239},
+ {237, 241},
+ },
+ {
+ {244, 240},
+ {238, 242},
+ },
+ {
+ {245, 241},
+ {239, 243},
+ },
+ {
+ {246, 242},
+ {240, 244},
+ },
+ {
+ {247, 243},
+ {241, 245},
+ },
+ {
+ {248, 244},
+ {242, 246},
+ },
+ {
+ {249, 245},
+ {243, 247},
+ },
+ {
+ {250, 246},
+ {244, 248},
+ },
+ {
+ {251, 247},
+ {245, 249},
+ },
+ {
+ {252, 248},
+ {246, 250},
+ },
+ {
+ {253, 249},
+ {247, 251},
+ },
+ {
+ {254, 250},
+ {248, 252},
+ },
+ {
+ {255, 251},
+ {249, 253},
+ },
+ {
+ {255, 252},
+ {250, 254},
+ },
+ {
+ {255, 253},
+ {251, 255},
+ },
+ {
+ {255, 254},
+ {252, 255},
+ },
+ {
+ {255, 255},
+ {253, 255},
+ },
+};
+
diff --git a/src/vid_voodoo_fb.c b/src/vid_voodoo_fb.c
new file mode 100644
index 0000000..cbf8c17
--- /dev/null
+++ b/src/vid_voodoo_fb.c
@@ -0,0 +1,447 @@
+#include "ibm.h"
+#include "device.h"
+#include "mem.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_svga.h"
+#include "vid_voodoo.h"
+#include "vid_voodoo_common.h"
+#include "vid_voodoo_dither.h"
+#include "vid_voodoo_regs.h"
+#include "vid_voodoo_render.h"
+#include "vid_voodoo_fb.h"
+
+uint16_t voodoo_fb_readw(uint32_t addr, void *p)
+{
+ voodoo_t *voodoo = (voodoo_t *)p;
+ int x, y;
+ uint32_t read_addr;
+ uint16_t temp;
+
+ if (voodoo->type >= VOODOO_BANSHEE)
+ {
+ x = addr & 0xffe;
+ y = (addr >> 12) & 0x3ff;
+ }
+ else
+ {
+ x = addr & 0x7fe;
+ y = (addr >> 11) & 0x3ff;
+ }
+
+ if (SLI_ENABLED)
+ {
+ voodoo_set_t *set = voodoo->set;
+
+ if (y & 1)
+ voodoo = set->voodoos[1];
+ else
+ voodoo = set->voodoos[0];
+
+ y >>= 1;
+ }
+
+ if (voodoo->col_tiled)
+ read_addr = voodoo->fb_read_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
+ else
+ read_addr = voodoo->fb_read_offset + x + (y * voodoo->row_width);
+
+ if (read_addr > voodoo->fb_mask)
+ return 0xffff;
+
+ temp = *(uint16_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]);
+
+// pclog("voodoo_fb_readw : %08X %08X %i %i %08X %08X %08x:%08x %i\n", addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++);
+ return temp;
+}
+uint32_t voodoo_fb_readl(uint32_t addr, void *p)
+{
+ voodoo_t *voodoo = (voodoo_t *)p;
+ int x, y;
+ uint32_t read_addr;
+ uint32_t temp;
+
+ if (voodoo->type >= VOODOO_BANSHEE)
+ {
+ x = addr & 0xffe;
+ y = (addr >> 12) & 0x3ff;
+ }
+ else
+ {
+ x = addr & 0x7fe;
+ y = (addr >> 11) & 0x3ff;
+ }
+
+ if (SLI_ENABLED)
+ {
+ voodoo_set_t *set = voodoo->set;
+
+ if (y & 1)
+ voodoo = set->voodoos[1];
+ else
+ voodoo = set->voodoos[0];
+
+ y >>= 1;
+ }
+
+ if (voodoo->col_tiled)
+ read_addr = voodoo->fb_read_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
+ else
+ read_addr = voodoo->fb_read_offset + x + (y * voodoo->row_width);
+
+ if (read_addr > voodoo->fb_mask)
+ return 0xffffffff;
+
+ temp = *(uint32_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]);
+
+// pclog("voodoo_fb_readl : %08X %08x %08X x=%i y=%i %08X %08X %08x:%08x %i ro=%08x rw=%i\n", addr, read_addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++, voodoo->fb_read_offset, voodoo->row_width);
+ return temp;
+}
+
+static inline uint16_t do_dither(voodoo_params_t *params, rgba8_t col, int x, int y)
+{
+ int r, g, b;
+
+ if (dither)
+ {
+ if (dither2x2)
+ {
+ r = dither_rb2x2[col.r][y & 1][x & 1];
+ g = dither_g2x2[col.g][y & 1][x & 1];
+ b = dither_rb2x2[col.b][y & 1][x & 1];
+ }
+ else
+ {
+ r = dither_rb[col.r][y & 3][x & 3];
+ g = dither_g[col.g][y & 3][x & 3];
+ b = dither_rb[col.b][y & 3][x & 3];
+ }
+ }
+ else
+ {
+ r = col.r >> 3;
+ g = col.g >> 2;
+ b = col.b >> 3;
+ }
+
+ return b | (g << 5) | (r << 11);
+}
+
+void voodoo_fb_writew(uint32_t addr, uint16_t val, void *p)
+{
+ voodoo_t *voodoo = (voodoo_t *)p;
+ voodoo_params_t *params = &voodoo->params;
+ int x, y;
+ uint32_t write_addr, write_addr_aux;
+ rgba8_t colour_data;
+ uint16_t depth_data;
+ uint8_t alpha_data;
+ int write_mask = 0;
+
+ colour_data.r = colour_data.g = colour_data.b = colour_data.a = 0;
+
+ depth_data = voodoo->params.zaColor & 0xffff;
+ alpha_data = voodoo->params.zaColor >> 24;
+
+// while (!RB_EMPTY)
+// thread_reset_event(voodoo->not_full_event);
+
+// pclog("voodoo_fb_writew : %08X %04X\n", addr, val);
+
+
+ switch (voodoo->lfbMode & LFB_FORMAT_MASK)
+ {
+ case LFB_FORMAT_RGB565:
+ colour_data = rgb565[val];
+ alpha_data = 0xff;
+ write_mask = LFB_WRITE_COLOUR;
+ break;
+ case LFB_FORMAT_RGB555:
+ colour_data = argb1555[val];
+ alpha_data = 0xff;
+ write_mask = LFB_WRITE_COLOUR;
+ break;
+ case LFB_FORMAT_ARGB1555:
+ colour_data = argb1555[val];
+ alpha_data = colour_data.a;
+ write_mask = LFB_WRITE_COLOUR;
+ break;
+ case LFB_FORMAT_DEPTH:
+ depth_data = val;
+ write_mask = LFB_WRITE_DEPTH;
+ break;
+
+ default:
+ fatal("voodoo_fb_writew : bad LFB format %08X\n", voodoo->lfbMode);
+ }
+
+ if (voodoo->type >= VOODOO_BANSHEE)
+ {
+ x = addr & 0xffe;
+ y = (addr >> 12) & 0x3ff;
+ }
+ else
+ {
+ x = addr & 0x7fe;
+ y = (addr >> 11) & 0x3ff;
+ }
+
+ if (SLI_ENABLED)
+ {
+ if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) ||
+ ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1)))
+ return;
+ y >>= 1;
+ }
+
+
+ if (voodoo->fb_write_offset == voodoo->params.front_offset && y < 2048)
+ voodoo->dirty_line[y] = 1;
+
+ if (voodoo->col_tiled)
+ write_addr = voodoo->fb_write_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
+ else
+ write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width);
+ if (voodoo->aux_tiled)
+ write_addr_aux = voodoo->params.aux_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
+ else
+ write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width);
+
+// pclog("fb_writew %08x %i %i %i %08x\n", addr, x, y, voodoo->row_width, write_addr);
+
+ if (voodoo->lfbMode & 0x100)
+ {
+ {
+ rgba8_t write_data = colour_data;
+ uint16_t new_depth = depth_data;
+
+ if (params->fbzMode & FBZ_DEPTH_ENABLE)
+ {
+ uint16_t old_depth = *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]);
+
+ DEPTH_TEST(new_depth);
+ }
+
+ if ((params->fbzMode & FBZ_CHROMAKEY) &&
+ write_data.r == params->chromaKey_r &&
+ write_data.g == params->chromaKey_g &&
+ write_data.b == params->chromaKey_b)
+ goto skip_pixel;
+
+ if (params->fogMode & FOG_ENABLE)
+ {
+ int32_t z = new_depth << 12;
+ int64_t w_depth = (int64_t)(int32_t)new_depth;
+ int32_t ia = alpha_data << 12;
+
+ APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth);
+ }
+
+ if (params->alphaMode & 1)
+ ALPHA_TEST(alpha_data);
+
+ if (params->alphaMode & (1 << 4))
+ {
+ uint16_t dat = *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]);
+ int dest_r, dest_g, dest_b, dest_a;
+
+ dest_r = (dat >> 8) & 0xf8;
+ dest_g = (dat >> 3) & 0xfc;
+ dest_b = (dat << 3) & 0xf8;
+ dest_r |= (dest_r >> 5);
+ dest_g |= (dest_g >> 6);
+ dest_b |= (dest_b >> 5);
+ dest_a = 0xff;
+
+ ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data);
+ }
+
+ if (params->fbzMode & FBZ_RGB_WMASK)
+ *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, x >> 1, y);
+ if (params->fbzMode & FBZ_DEPTH_WMASK)
+ *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth;
+
+skip_pixel:
+ x = x;
+ }
+ }
+ else
+ {
+ if (write_mask & LFB_WRITE_COLOUR)
+ *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data, x >> 1, y);
+ if (write_mask & LFB_WRITE_DEPTH)
+ *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data;
+ }
+}
+
+
+void voodoo_fb_writel(uint32_t addr, uint32_t val, void *p)
+{
+ voodoo_t *voodoo = (voodoo_t *)p;
+ voodoo_params_t *params = &voodoo->params;
+ int x, y;
+ uint32_t write_addr, write_addr_aux;
+ rgba8_t colour_data[2];
+ uint16_t depth_data[2];
+ uint8_t alpha_data[2];
+ int write_mask = 0, count = 1;
+
+ depth_data[0] = depth_data[1] = voodoo->params.zaColor & 0xffff;
+ alpha_data[0] = alpha_data[1] = voodoo->params.zaColor >> 24;
+// while (!RB_EMPTY)
+// thread_reset_event(voodoo->not_full_event);
+
+// pclog("voodoo_fb_writel : %08X %08X\n", addr, val);
+
+ switch (voodoo->lfbMode & LFB_FORMAT_MASK)
+ {
+ case LFB_FORMAT_RGB565:
+ colour_data[0] = rgb565[val & 0xffff];
+ colour_data[1] = rgb565[val >> 16];
+ write_mask = LFB_WRITE_COLOUR;
+ count = 2;
+ break;
+ case LFB_FORMAT_RGB555:
+ colour_data[0] = argb1555[val & 0xffff];
+ colour_data[1] = argb1555[val >> 16];
+ write_mask = LFB_WRITE_COLOUR;
+ count = 2;
+ break;
+ case LFB_FORMAT_ARGB1555:
+ colour_data[0] = argb1555[val & 0xffff];
+ alpha_data[0] = colour_data[0].a;
+ colour_data[1] = argb1555[val >> 16];
+ alpha_data[1] = colour_data[1].a;
+ write_mask = LFB_WRITE_COLOUR;
+ count = 2;
+ break;
+
+ case LFB_FORMAT_ARGB8888:
+ colour_data[0].b = val & 0xff;
+ colour_data[0].g = (val >> 8) & 0xff;
+ colour_data[0].r = (val >> 16) & 0xff;
+ alpha_data[0] = (val >> 24) & 0xff;
+ write_mask = LFB_WRITE_COLOUR;
+ addr >>= 1;
+ break;
+
+ case LFB_FORMAT_DEPTH:
+ depth_data[0] = val;
+ depth_data[1] = val >> 16;
+ write_mask = LFB_WRITE_DEPTH;
+ count = 2;
+ break;
+
+ default:
+ fatal("voodoo_fb_writel : bad LFB format %08X\n", voodoo->lfbMode);
+ }
+
+ if (voodoo->type >= VOODOO_BANSHEE)
+ {
+ x = addr & 0xffe;
+ y = (addr >> 12) & 0x3ff;
+ }
+ else
+ {
+ x = addr & 0x7fe;
+ y = (addr >> 11) & 0x3ff;
+ }
+
+ if (SLI_ENABLED)
+ {
+ if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) ||
+ ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1)))
+ return;
+ y >>= 1;
+ }
+
+ if (voodoo->fb_write_offset == voodoo->params.front_offset && y < 2048)
+ voodoo->dirty_line[y] = 1;
+
+ if (voodoo->col_tiled)
+ write_addr = voodoo->fb_write_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
+ else
+ write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width);
+ if (voodoo->aux_tiled)
+ write_addr_aux = voodoo->params.aux_offset + (x & 127) + (x >> 7) * 128*32 + (y & 31) * 128 + (y >> 5) * voodoo->row_width;
+ else
+ write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width);
+
+// pclog("fb_writel %08x x=%i y=%i rw=%i %08x wo=%08x\n", addr, x, y, voodoo->row_width, write_addr, voodoo->fb_write_offset);
+
+ if (voodoo->lfbMode & 0x100)
+ {
+ int c;
+
+ for (c = 0; c < count; c++)
+ {
+ rgba8_t write_data = colour_data[c];
+ uint16_t new_depth = depth_data[c];
+
+ if (params->fbzMode & FBZ_DEPTH_ENABLE)
+ {
+ uint16_t old_depth = *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]);
+
+ DEPTH_TEST(new_depth);
+ }
+
+ if ((params->fbzMode & FBZ_CHROMAKEY) &&
+ write_data.r == params->chromaKey_r &&
+ write_data.g == params->chromaKey_g &&
+ write_data.b == params->chromaKey_b)
+ goto skip_pixel;
+
+ if (params->fogMode & FOG_ENABLE)
+ {
+ int32_t z = new_depth << 12;
+ int64_t w_depth = new_depth;
+ int32_t ia = alpha_data[c] << 12;
+
+ APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth);
+ }
+
+ if (params->alphaMode & 1)
+ ALPHA_TEST(alpha_data[c]);
+
+ if (params->alphaMode & (1 << 4))
+ {
+ uint16_t dat = *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]);
+ int dest_r, dest_g, dest_b, dest_a;
+
+ dest_r = (dat >> 8) & 0xf8;
+ dest_g = (dat >> 3) & 0xfc;
+ dest_b = (dat << 3) & 0xf8;
+ dest_r |= (dest_r >> 5);
+ dest_g |= (dest_g >> 6);
+ dest_b |= (dest_b >> 5);
+ dest_a = 0xff;
+
+ ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data[c]);
+ }
+
+ if (params->fbzMode & FBZ_RGB_WMASK)
+ *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, (x >> 1) + c, y);
+ if (params->fbzMode & FBZ_DEPTH_WMASK)
+ *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth;
+
+skip_pixel:
+ write_addr += 2;
+ write_addr_aux += 2;
+ }
+ }
+ else
+ {
+ int c;
+
+ for (c = 0; c < count; c++)
+ {
+ if (write_mask & LFB_WRITE_COLOUR)
+ *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y);
+ if (write_mask & LFB_WRITE_DEPTH)
+ *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data[c];
+
+ write_addr += 2;
+ write_addr_aux += 2;
+ }
+ }
+}
diff --git a/src/vid_voodoo_fb.h b/src/vid_voodoo_fb.h
new file mode 100644
index 0000000..fcb2513
--- /dev/null
+++ b/src/vid_voodoo_fb.h
@@ -0,0 +1,4 @@
+uint16_t voodoo_fb_readw(uint32_t addr, void *p);
+uint32_t voodoo_fb_readl(uint32_t addr, void *p);
+void voodoo_fb_writew(uint32_t addr, uint16_t val, void *p);
+void voodoo_fb_writel(uint32_t addr, uint32_t val, void *p);
diff --git a/src/vid_voodoo_fifo.c b/src/vid_voodoo_fifo.c
new file mode 100644
index 0000000..59861f3
--- /dev/null
+++ b/src/vid_voodoo_fifo.c
@@ -0,0 +1,503 @@
+#include
+#include
+#include "ibm.h"
+#include "device.h"
+#include "mem.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_svga.h"
+#include "vid_voodoo.h"
+#include "vid_voodoo_common.h"
+#include "vid_voodoo_banshee_blitter.h"
+#include "vid_voodoo_fb.h"
+#include "vid_voodoo_fifo.h"
+#include "vid_voodoo_reg.h"
+#include "vid_voodoo_regs.h"
+#include "vid_voodoo_render.h"
+#include "vid_voodoo_texture.h"
+
+#define WAKE_DELAY (TIMER_USEC * 100)
+void voodoo_wake_fifo_thread(voodoo_t *voodoo)
+{
+ if (!timer_is_enabled(&voodoo->wake_timer))
+ {
+ /*Don't wake FIFO thread immediately - if we do that it will probably
+ process one word and go back to sleep, requiring it to be woken on
+ almost every write. Instead, wait a short while so that the CPU
+ emulation writes more data so we have more batched-up work.*/
+ timer_set_delay_u64(&voodoo->wake_timer, WAKE_DELAY);
+ }
+}
+
+void voodoo_wake_fifo_thread_now(voodoo_t *voodoo)
+{
+ thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
+}
+
+void voodoo_wake_timer(void *p)
+{
+ voodoo_t *voodoo = (voodoo_t *)p;
+
+ thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
+}
+
+void voodoo_queue_command(voodoo_t *voodoo, uint32_t addr_type, uint32_t val)
+{
+ fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_write_idx & FIFO_MASK];
+
+ while (FIFO_FULL)
+ {
+ thread_reset_event(voodoo->fifo_not_full_event);
+ if (FIFO_FULL)
+ {
+ thread_wait_event(voodoo->fifo_not_full_event, 1); /*Wait for room in ringbuffer*/
+ if (FIFO_FULL)
+ voodoo_wake_fifo_thread_now(voodoo);
+ }
+ }
+
+ fifo->val = val;
+ fifo->addr_type = addr_type;
+
+ voodoo->fifo_write_idx++;
+
+ if (FIFO_ENTRIES > 0xe000)
+ voodoo_wake_fifo_thread(voodoo);
+}
+
+void voodoo_flush(voodoo_t *voodoo)
+{
+ voodoo->flush = 1;
+ while (!FIFO_EMPTY)
+ {
+ voodoo_wake_fifo_thread_now(voodoo);
+ thread_wait_event(voodoo->fifo_not_full_event, 1);
+ }
+ voodoo_wait_for_render_thread_idle(voodoo);
+ voodoo->flush = 0;
+}
+
+void voodoo_wake_fifo_threads(voodoo_set_t *set, voodoo_t *voodoo)
+{
+ voodoo_wake_fifo_thread(voodoo);
+ if (SLI_ENABLED && voodoo->type != VOODOO_2 && set->voodoos[0] == voodoo)
+ voodoo_wake_fifo_thread(set->voodoos[1]);
+}
+
+void voodoo_wait_for_swap_complete(voodoo_t *voodoo)
+{
+ while (voodoo->swap_pending)
+ {
+ thread_wait_event(voodoo->wake_fifo_thread, -1);
+ thread_reset_event(voodoo->wake_fifo_thread);
+
+ thread_lock_mutex(voodoo->swap_mutex);
+ if ((voodoo->swap_pending && voodoo->flush) || FIFO_FULL)
+ {
+ /*Main thread is waiting for FIFO to empty, so skip vsync wait and just swap*/
+ memset(voodoo->dirty_line, 1, sizeof(voodoo->dirty_line));
+ voodoo->front_offset = voodoo->params.front_offset;
+ if (voodoo->swap_count > 0)
+ voodoo->swap_count--;
+ voodoo->swap_pending = 0;
+ thread_unlock_mutex(voodoo->swap_mutex);
+ break;
+ }
+ else
+ thread_unlock_mutex(voodoo->swap_mutex);
+ }
+}
+
+
+static uint32_t cmdfifo_get(voodoo_t *voodoo)
+{
+ uint32_t val;
+
+ if (!voodoo->cmdfifo_in_sub)
+ {
+ while (voodoo->cmdfifo_depth_rd == voodoo->cmdfifo_depth_wr)
+ {
+ thread_wait_event(voodoo->wake_fifo_thread, -1);
+ thread_reset_event(voodoo->wake_fifo_thread);
+ }
+ }
+
+ val = *(uint32_t *)&voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask];
+
+ if (!voodoo->cmdfifo_in_sub)
+ voodoo->cmdfifo_depth_rd++;
+ voodoo->cmdfifo_rp += 4;
+
+// pclog(" CMDFIFO get %08x\n", val);
+ return val;
+}
+
+static inline float cmdfifo_get_f(voodoo_t *voodoo)
+{
+ union
+ {
+ uint32_t i;
+ float f;
+ } tempif;
+
+ tempif.i = cmdfifo_get(voodoo);
+ return tempif.f;
+}
+
+enum
+{
+ CMDFIFO3_PC_MASK_RGB = (1 << 10),
+ CMDFIFO3_PC_MASK_ALPHA = (1 << 11),
+ CMDFIFO3_PC_MASK_Z = (1 << 12),
+ CMDFIFO3_PC_MASK_Wb = (1 << 13),
+ CMDFIFO3_PC_MASK_W0 = (1 << 14),
+ CMDFIFO3_PC_MASK_S0_T0 = (1 << 15),
+ CMDFIFO3_PC_MASK_W1 = (1 << 16),
+ CMDFIFO3_PC_MASK_S1_T1 = (1 << 17),
+
+ CMDFIFO3_PC = (1 << 28)
+};
+
+void voodoo_fifo_thread(void *param)
+{
+ voodoo_t *voodoo = (voodoo_t *)param;
+
+ while (1)
+ {
+ thread_set_event(voodoo->fifo_not_full_event);
+ thread_wait_event(voodoo->wake_fifo_thread, -1);
+ thread_reset_event(voodoo->wake_fifo_thread);
+ voodoo->voodoo_busy = 1;
+ while (!FIFO_EMPTY)
+ {
+ uint64_t start_time = timer_read();
+ uint64_t end_time;
+ fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
+
+ switch (fifo->addr_type & FIFO_TYPE)
+ {
+ case FIFO_WRITEL_REG:
+ while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_REG)
+ {
+ voodoo_reg_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
+ fifo->addr_type = FIFO_INVALID;
+ voodoo->fifo_read_idx++;
+ if (FIFO_EMPTY)
+ break;
+ fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
+ }
+ break;
+ case FIFO_WRITEW_FB:
+ voodoo_wait_for_render_thread_idle(voodoo);
+ while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEW_FB)
+ {
+ voodoo_fb_writew(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
+ fifo->addr_type = FIFO_INVALID;
+ voodoo->fifo_read_idx++;
+ if (FIFO_EMPTY)
+ break;
+ fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
+ }
+ break;
+ case FIFO_WRITEL_FB:
+ voodoo_wait_for_render_thread_idle(voodoo);
+ while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_FB)
+ {
+ voodoo_fb_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
+ fifo->addr_type = FIFO_INVALID;
+ voodoo->fifo_read_idx++;
+ if (FIFO_EMPTY)
+ break;
+ fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
+ }
+ break;
+ case FIFO_WRITEL_TEX:
+ while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_TEX)
+ {
+ if (!(fifo->addr_type & 0x400000))
+ voodoo_tex_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
+ fifo->addr_type = FIFO_INVALID;
+ voodoo->fifo_read_idx++;
+ if (FIFO_EMPTY)
+ break;
+ fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
+ }
+ break;
+ case FIFO_WRITEL_2DREG:
+ while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_2DREG)
+ {
+ voodoo_2d_reg_writel(voodoo, fifo->addr_type & FIFO_ADDR, fifo->val);
+ fifo->addr_type = FIFO_INVALID;
+ voodoo->fifo_read_idx++;
+ if (FIFO_EMPTY)
+ break;
+ fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
+ }
+ break;
+
+ default:
+ fatal("Unknown fifo entry %08x\n", fifo->addr_type);
+ }
+
+ if (FIFO_ENTRIES > 0xe000)
+ thread_set_event(voodoo->fifo_not_full_event);
+
+ end_time = timer_read();
+ voodoo->time += end_time - start_time;
+ }
+
+ while (voodoo->cmdfifo_enabled && (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr || voodoo->cmdfifo_in_sub))
+ {
+ uint64_t start_time = timer_read();
+ uint64_t end_time;
+ uint32_t header = cmdfifo_get(voodoo);
+ uint32_t addr;
+ uint32_t mask;
+ int smode;
+ int num;
+ int num_verticies;
+ int v_num;
+
+// pclog(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp);
+
+ switch (header & 7)
+ {
+ case 0:
+// pclog("CMDFIFO0\n");
+ switch ((header >> 3) & 7)
+ {
+ case 0: /*NOP*/
+ break;
+
+ case 1: /*JSR*/
+// pclog("JSR %08x\n", (header >> 4) & 0xfffffc);
+ voodoo->cmdfifo_ret_addr = voodoo->cmdfifo_rp;
+ voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc;
+ voodoo->cmdfifo_in_sub = 1;
+ break;
+
+ case 2: /*RET*/
+ voodoo->cmdfifo_rp = voodoo->cmdfifo_ret_addr;
+ voodoo->cmdfifo_in_sub = 0;
+ break;
+
+ case 3: /*JMP local frame buffer*/
+ voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc;
+// pclog("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header);
+ break;
+
+ default:
+ fatal("Bad CMDFIFO0 %08x\n", header);
+ }
+ break;
+
+ case 1:
+ num = header >> 16;
+ addr = (header & 0x7ff8) >> 1;
+// pclog("CMDFIFO1 addr=%08x\n",addr);
+ while (num--)
+ {
+ uint32_t val = cmdfifo_get(voodoo);
+ if ((addr & (1 << 13)) && voodoo->type >= VOODOO_BANSHEE)
+ {
+// if (voodoo->type != VOODOO_BANSHEE)
+// fatal("CMDFIFO1: Not Banshee\n");
+// pclog("CMDFIFO1: write %08x %08x\n", addr, val);
+ voodoo_2d_reg_writel(voodoo, addr, val);
+ }
+ else
+ {
+ if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD ||
+ (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD)
+ voodoo->cmd_written_fifo++;
+
+ if (voodoo->type >= VOODOO_BANSHEE && (addr & 0x3ff) == SST_swapbufferCMD)
+ voodoo->cmd_written_fifo++;
+ voodoo_reg_writel(addr, val, voodoo);
+ }
+
+ if (header & (1 << 15))
+ addr += 4;
+ }
+ break;
+
+ case 2:
+ if (voodoo->type < VOODOO_BANSHEE)
+ fatal("CMDFIFO2: Not Banshee\n");
+ mask = (header >> 3);
+ addr = 8;
+ while (mask)
+ {
+ if (mask & 1)
+ {
+ uint32_t val = cmdfifo_get(voodoo);
+
+ voodoo_2d_reg_writel(voodoo, addr, val);
+ }
+
+ addr += 4;
+ mask >>= 1;
+ }
+ break;
+
+ case 3:
+ num = (header >> 29) & 7;
+ mask = header;//(header >> 10) & 0xff;
+ smode = (header >> 22) & 0xf;
+ voodoo_reg_writel(SST_sSetupMode, ((header >> 10) & 0xff) | (smode << 16), voodoo);
+ num_verticies = (header >> 6) & 0xf;
+ v_num = 0;
+ if (((header >> 3) & 7) == 2)
+ v_num = 1;
+// pclog("CMDFIFO3: num=%i verts=%i mask=%02x\n", num, num_verticies, (header >> 10) & 0xff);
+// pclog("CMDFIFO3 %02x %i\n", (header >> 10), (header >> 3) & 7);
+
+ while (num_verticies--)
+ {
+ voodoo->verts[3].sVx = cmdfifo_get_f(voodoo);
+ voodoo->verts[3].sVy = cmdfifo_get_f(voodoo);
+ if (mask & CMDFIFO3_PC_MASK_RGB)
+ {
+ if (header & CMDFIFO3_PC)
+ {
+ uint32_t val = cmdfifo_get(voodoo);
+ voodoo->verts[3].sBlue = (float)(val & 0xff);
+ voodoo->verts[3].sGreen = (float)((val >> 8) & 0xff);
+ voodoo->verts[3].sRed = (float)((val >> 16) & 0xff);
+ voodoo->verts[3].sAlpha = (float)((val >> 24) & 0xff);
+ }
+ else
+ {
+ voodoo->verts[3].sRed = cmdfifo_get_f(voodoo);
+ voodoo->verts[3].sGreen = cmdfifo_get_f(voodoo);
+ voodoo->verts[3].sBlue = cmdfifo_get_f(voodoo);
+ }
+ }
+ if ((mask & CMDFIFO3_PC_MASK_ALPHA) && !(header & CMDFIFO3_PC))
+ voodoo->verts[3].sAlpha = cmdfifo_get_f(voodoo);
+ if (mask & CMDFIFO3_PC_MASK_Z)
+ voodoo->verts[3].sVz = cmdfifo_get_f(voodoo);
+ if (mask & CMDFIFO3_PC_MASK_Wb)
+ voodoo->verts[3].sWb = cmdfifo_get_f(voodoo);
+ if (mask & CMDFIFO3_PC_MASK_W0)
+ voodoo->verts[3].sW0 = cmdfifo_get_f(voodoo);
+ if (mask & CMDFIFO3_PC_MASK_S0_T0)
+ {
+ voodoo->verts[3].sS0 = cmdfifo_get_f(voodoo);
+ voodoo->verts[3].sT0 = cmdfifo_get_f(voodoo);
+ }
+ if (mask & CMDFIFO3_PC_MASK_W1)
+ voodoo->verts[3].sW1 = cmdfifo_get_f(voodoo);
+ if (mask & CMDFIFO3_PC_MASK_S1_T1)
+ {
+ voodoo->verts[3].sS1 = cmdfifo_get_f(voodoo);
+ voodoo->verts[3].sT1 = cmdfifo_get_f(voodoo);
+ }
+ if (v_num)
+ voodoo_reg_writel(SST_sDrawTriCMD, 0, voodoo);
+ else
+ voodoo_reg_writel(SST_sBeginTriCMD, 0, voodoo);
+ v_num++;
+ if (v_num == 3 && ((header >> 3) & 7) == 0)
+ v_num = 0;
+ }
+ break;
+
+ case 4:
+ num = (header >> 29) & 7;
+ mask = (header >> 15) & 0x3fff;
+ addr = (header & 0x7ff8) >> 1;
+// pclog("CMDFIFO4 addr=%08x\n",addr);
+ while (mask)
+ {
+ if (mask & 1)
+ {
+ uint32_t val = cmdfifo_get(voodoo);
+
+ if ((addr & (1 << 13)) && voodoo->type >= VOODOO_BANSHEE)
+ {
+ if (voodoo->type < VOODOO_BANSHEE)
+ fatal("CMDFIFO1: Not Banshee\n");
+// pclog("CMDFIFO1: write %08x %08x\n", addr, val);
+ voodoo_2d_reg_writel(voodoo, addr, val);
+ }
+ else
+ {
+ if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD ||
+ (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD)
+ voodoo->cmd_written_fifo++;
+
+ if (voodoo->type >= VOODOO_BANSHEE && (addr & 0x3ff) == SST_swapbufferCMD)
+ voodoo->cmd_written_fifo++;
+ voodoo_reg_writel(addr, val, voodoo);
+ }
+ }
+
+ addr += 4;
+ mask >>= 1;
+ }
+ while (num--)
+ cmdfifo_get(voodoo);
+ break;
+
+ case 5:
+// if (header & 0x3fc00000)
+// fatal("CMDFIFO packet 5 has byte disables set %08x\n", header);
+ num = (header >> 3) & 0x7ffff;
+ addr = cmdfifo_get(voodoo) & 0xffffff;
+ if (!num)
+ num = 1;
+// pclog("CMDFIFO5 addr=%08x num=%i\n", addr, num);
+ switch (header >> 30)
+ {
+ case 0: /*Linear framebuffer (Banshee)*/
+ if (voodoo->texture_present[0][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT])
+ {
+// pclog("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT);
+ flush_texture_cache(voodoo, addr & voodoo->texture_mask, 0);
+ }
+ if (voodoo->texture_present[1][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT])
+ {
+// pclog("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT);
+ flush_texture_cache(voodoo, addr & voodoo->texture_mask, 1);
+ }
+ while (num--)
+ {
+ uint32_t val = cmdfifo_get(voodoo);
+ if (addr <= voodoo->fb_mask)
+ *(uint32_t *)&voodoo->fb_mem[addr] = val;
+ addr += 4;
+ }
+ break;
+ case 2: /*Framebuffer*/
+ while (num--)
+ {
+ uint32_t val = cmdfifo_get(voodoo);
+ voodoo_fb_writel(addr, val, voodoo);
+ addr += 4;
+ }
+ break;
+ case 3: /*Texture*/
+ while (num--)
+ {
+ uint32_t val = cmdfifo_get(voodoo);
+ voodoo_tex_writel(addr, val, voodoo);
+ addr += 4;
+ }
+ break;
+
+ default:
+ fatal("CMDFIFO packet 5 bad space %08x %08x\n", header, voodoo->cmdfifo_rp);
+ }
+ break;
+
+ default:
+ fatal("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp);
+ }
+
+ end_time = timer_read();
+ voodoo->time += end_time - start_time;
+ }
+ voodoo->voodoo_busy = 0;
+ }
+}
diff --git a/src/vid_voodoo_fifo.h b/src/vid_voodoo_fifo.h
new file mode 100644
index 0000000..c1caeba
--- /dev/null
+++ b/src/vid_voodoo_fifo.h
@@ -0,0 +1,8 @@
+void voodoo_wake_fifo_thread(voodoo_t *voodoo);
+void voodoo_wake_fifo_thread_now(voodoo_t *voodoo);
+void voodoo_wake_timer(void *p);
+void voodoo_queue_command(voodoo_t *voodoo, uint32_t addr_type, uint32_t val);
+void voodoo_flush(voodoo_t *voodoo);
+void voodoo_wake_fifo_threads(voodoo_set_t *set, voodoo_t *voodoo);
+void voodoo_wait_for_swap_complete(voodoo_t *voodoo);
+void voodoo_fifo_thread(void *param);
diff --git a/src/vid_voodoo_reg.c b/src/vid_voodoo_reg.c
new file mode 100644
index 0000000..63e590b
--- /dev/null
+++ b/src/vid_voodoo_reg.c
@@ -0,0 +1,1321 @@
+#include
+#include
+#include "ibm.h"
+#include "device.h"
+#include "mem.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_svga.h"
+#include "vid_voodoo.h"
+#include "vid_voodoo_common.h"
+#include "vid_voodoo_banshee.h"
+#include "vid_voodoo_blitter.h"
+#include "vid_voodoo_dither.h"
+#include "vid_voodoo_fifo.h"
+#include "vid_voodoo_reg.h"
+#include "vid_voodoo_regs.h"
+#include "vid_voodoo_render.h"
+#include "vid_voodoo_setup.h"
+#include "vid_voodoo_texture.h"
+
+enum
+{
+ CHIP_FBI = 0x1,
+ CHIP_TREX0 = 0x2,
+ CHIP_TREX1 = 0x4,
+ CHIP_TREX2 = 0x8
+};
+
+void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
+{
+ voodoo_t *voodoo = (voodoo_t *)p;
+ union
+ {
+ uint32_t i;
+ float f;
+ } tempif;
+ int ad21 = addr & (1 << 21);
+ int chip = (addr >> 10) & 0xf;
+ if (!chip)
+ chip = 0xf;
+
+ tempif.i = val;
+//pclog("voodoo_reg_write_l: addr=%08x val=%08x(%f) chip=%x\n", addr, val, tempif.f, chip);
+ addr &= 0x3fc;
+
+ if ((voodoo->fbiInit3 & FBIINIT3_REMAP) && addr < 0x100 && ad21)
+ addr |= 0x400;
+ switch (addr)
+ {
+ case SST_swapbufferCMD:
+ if (voodoo->type >= VOODOO_BANSHEE)
+ {
+// pclog("swapbufferCMD %08x %08x\n", val, voodoo->leftOverlayBuf);
+
+ voodoo_wait_for_render_thread_idle(voodoo);
+ if (!(val & 1))
+ {
+ banshee_set_overlay_addr(voodoo->p, voodoo->leftOverlayBuf);
+ thread_lock_mutex(voodoo->swap_mutex);
+ if (voodoo->swap_count > 0)
+ voodoo->swap_count--;
+ thread_unlock_mutex(voodoo->swap_mutex);
+ voodoo->frame_count++;
+ }
+ else if (TRIPLE_BUFFER)
+ {
+ if (voodoo->swap_pending)
+ voodoo_wait_for_swap_complete(voodoo);
+ voodoo->swap_interval = (val >> 1) & 0xff;
+ voodoo->swap_offset = voodoo->leftOverlayBuf;
+ voodoo->swap_pending = 1;
+ }
+ else
+ {
+ voodoo->swap_interval = (val >> 1) & 0xff;
+ voodoo->swap_offset = voodoo->leftOverlayBuf;
+ voodoo->swap_pending = 1;
+
+ voodoo_wait_for_swap_complete(voodoo);
+ }
+
+ voodoo->cmd_read++;
+ break;
+ }
+
+ if (TRIPLE_BUFFER)
+ {
+ voodoo->disp_buffer = (voodoo->disp_buffer + 1) % 3;
+ voodoo->draw_buffer = (voodoo->draw_buffer + 1) % 3;
+ }
+ else
+ {
+ voodoo->disp_buffer = !voodoo->disp_buffer;
+ voodoo->draw_buffer = !voodoo->draw_buffer;
+ }
+ voodoo_recalc(voodoo);
+
+ voodoo->params.swapbufferCMD = val;
+
+// pclog("Swap buffer %08x %d %p %i\n", val, voodoo->swap_count, &voodoo->swap_count, (voodoo == voodoo->set->voodoos[1]) ? 1 : 0);
+// voodoo->front_offset = params->front_offset;
+ voodoo_wait_for_render_thread_idle(voodoo);
+ if (!(val & 1))
+ {
+ memset(voodoo->dirty_line, 1, sizeof(voodoo->dirty_line));
+ voodoo->front_offset = voodoo->params.front_offset;
+ thread_lock_mutex(voodoo->swap_mutex);
+ if (voodoo->swap_count > 0)
+ voodoo->swap_count--;
+ thread_unlock_mutex(voodoo->swap_mutex);
+ }
+ else if (TRIPLE_BUFFER)
+ {
+ if (voodoo->swap_pending)
+ voodoo_wait_for_swap_complete(voodoo);
+
+ voodoo->swap_interval = (val >> 1) & 0xff;
+ voodoo->swap_offset = voodoo->params.front_offset;
+ voodoo->swap_pending = 1;
+ }
+ else
+ {
+ voodoo->swap_interval = (val >> 1) & 0xff;
+ voodoo->swap_offset = voodoo->params.front_offset;
+ voodoo->swap_pending = 1;
+
+ voodoo_wait_for_swap_complete(voodoo);
+ }
+ voodoo->cmd_read++;
+ break;
+
+ case SST_vertexAx: case SST_remap_vertexAx:
+ voodoo->params.vertexAx = val & 0xffff;
+ break;
+ case SST_vertexAy: case SST_remap_vertexAy:
+ voodoo->params.vertexAy = val & 0xffff;
+ break;
+ case SST_vertexBx: case SST_remap_vertexBx:
+ voodoo->params.vertexBx = val & 0xffff;
+ break;
+ case SST_vertexBy: case SST_remap_vertexBy:
+ voodoo->params.vertexBy = val & 0xffff;
+ break;
+ case SST_vertexCx: case SST_remap_vertexCx:
+ voodoo->params.vertexCx = val & 0xffff;
+ break;
+ case SST_vertexCy: case SST_remap_vertexCy:
+ voodoo->params.vertexCy = val & 0xffff;
+ break;
+
+ case SST_startR: case SST_remap_startR:
+ voodoo->params.startR = val & 0xffffff;
+ break;
+ case SST_startG: case SST_remap_startG:
+ voodoo->params.startG = val & 0xffffff;
+ break;
+ case SST_startB: case SST_remap_startB:
+ voodoo->params.startB = val & 0xffffff;
+ break;
+ case SST_startZ: case SST_remap_startZ:
+ voodoo->params.startZ = val;
+ break;
+ case SST_startA: case SST_remap_startA:
+ voodoo->params.startA = val & 0xffffff;
+ break;
+ case SST_startS: case SST_remap_startS:
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].startS = ((int64_t)(int32_t)val) << 14;
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].startS = ((int64_t)(int32_t)val) << 14;
+ break;
+ case SST_startT: case SST_remap_startT:
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].startT = ((int64_t)(int32_t)val) << 14;
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].startT = ((int64_t)(int32_t)val) << 14;
+ break;
+ case SST_startW: case SST_remap_startW:
+ if (chip & CHIP_FBI)
+ voodoo->params.startW = (int64_t)(int32_t)val << 2;
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].startW = (int64_t)(int32_t)val << 2;
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].startW = (int64_t)(int32_t)val << 2;
+ break;
+
+ case SST_dRdX: case SST_remap_dRdX:
+ voodoo->params.dRdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
+ break;
+ case SST_dGdX: case SST_remap_dGdX:
+ voodoo->params.dGdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
+ break;
+ case SST_dBdX: case SST_remap_dBdX:
+ voodoo->params.dBdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
+ break;
+ case SST_dZdX: case SST_remap_dZdX:
+ voodoo->params.dZdX = val;
+ break;
+ case SST_dAdX: case SST_remap_dAdX:
+ voodoo->params.dAdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
+ break;
+ case SST_dSdX: case SST_remap_dSdX:
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].dSdX = ((int64_t)(int32_t)val) << 14;
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].dSdX = ((int64_t)(int32_t)val) << 14;
+ break;
+ case SST_dTdX: case SST_remap_dTdX:
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].dTdX = ((int64_t)(int32_t)val) << 14;
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].dTdX = ((int64_t)(int32_t)val) << 14;
+ break;
+ case SST_dWdX: case SST_remap_dWdX:
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].dWdX = (int64_t)(int32_t)val << 2;
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].dWdX = (int64_t)(int32_t)val << 2;
+ if (chip & CHIP_FBI)
+ voodoo->params.dWdX = (int64_t)(int32_t)val << 2;
+ break;
+
+ case SST_dRdY: case SST_remap_dRdY:
+ voodoo->params.dRdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
+ break;
+ case SST_dGdY: case SST_remap_dGdY:
+ voodoo->params.dGdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
+ break;
+ case SST_dBdY: case SST_remap_dBdY:
+ voodoo->params.dBdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
+ break;
+ case SST_dZdY: case SST_remap_dZdY:
+ voodoo->params.dZdY = val;
+ break;
+ case SST_dAdY: case SST_remap_dAdY:
+ voodoo->params.dAdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
+ break;
+ case SST_dSdY: case SST_remap_dSdY:
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].dSdY = ((int64_t)(int32_t)val) << 14;
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].dSdY = ((int64_t)(int32_t)val) << 14;
+ break;
+ case SST_dTdY: case SST_remap_dTdY:
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].dTdY = ((int64_t)(int32_t)val) << 14;
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].dTdY = ((int64_t)(int32_t)val) << 14;
+ break;
+ case SST_dWdY: case SST_remap_dWdY:
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].dWdY = (int64_t)(int32_t)val << 2;
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].dWdY = (int64_t)(int32_t)val << 2;
+ if (chip & CHIP_FBI)
+ voodoo->params.dWdY = (int64_t)(int32_t)val << 2;
+ break;
+
+ case SST_triangleCMD: case SST_remap_triangleCMD:
+ voodoo->params.sign = val & (1 << 31);
+
+ if (voodoo->ncc_dirty[0])
+ voodoo_update_ncc(voodoo, 0);
+ if (voodoo->ncc_dirty[1])
+ voodoo_update_ncc(voodoo, 1);
+ voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0;
+
+ voodoo_queue_triangle(voodoo, &voodoo->params);
+
+ voodoo->cmd_read++;
+ break;
+
+ case SST_fvertexAx: case SST_remap_fvertexAx:
+ voodoo->fvertexAx.i = val;
+ voodoo->params.vertexAx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexAx.f * 16.0f) & 0xffff;
+ break;
+ case SST_fvertexAy: case SST_remap_fvertexAy:
+ voodoo->fvertexAy.i = val;
+ voodoo->params.vertexAy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexAy.f * 16.0f) & 0xffff;
+ break;
+ case SST_fvertexBx: case SST_remap_fvertexBx:
+ voodoo->fvertexBx.i = val;
+ voodoo->params.vertexBx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexBx.f * 16.0f) & 0xffff;
+ break;
+ case SST_fvertexBy: case SST_remap_fvertexBy:
+ voodoo->fvertexBy.i = val;
+ voodoo->params.vertexBy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexBy.f * 16.0f) & 0xffff;
+ break;
+ case SST_fvertexCx: case SST_remap_fvertexCx:
+ voodoo->fvertexCx.i = val;
+ voodoo->params.vertexCx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexCx.f * 16.0f) & 0xffff;
+ break;
+ case SST_fvertexCy: case SST_remap_fvertexCy:
+ voodoo->fvertexCy.i = val;
+ voodoo->params.vertexCy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexCy.f * 16.0f) & 0xffff;
+ break;
+
+ case SST_fstartR: case SST_remap_fstartR:
+ tempif.i = val;
+ voodoo->params.startR = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fstartG: case SST_remap_fstartG:
+ tempif.i = val;
+ voodoo->params.startG = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fstartB: case SST_remap_fstartB:
+ tempif.i = val;
+ voodoo->params.startB = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fstartZ: case SST_remap_fstartZ:
+ tempif.i = val;
+ voodoo->params.startZ = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fstartA: case SST_remap_fstartA:
+ tempif.i = val;
+ voodoo->params.startA = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fstartS: case SST_remap_fstartS:
+ tempif.i = val;
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].startS = (int64_t)(tempif.f * 4294967296.0f);
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].startS = (int64_t)(tempif.f * 4294967296.0f);
+ break;
+ case SST_fstartT: case SST_remap_fstartT:
+ tempif.i = val;
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].startT = (int64_t)(tempif.f * 4294967296.0f);
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].startT = (int64_t)(tempif.f * 4294967296.0f);
+ break;
+ case SST_fstartW: case SST_remap_fstartW:
+ tempif.i = val;
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].startW = (int64_t)(tempif.f * 4294967296.0f);
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].startW = (int64_t)(tempif.f * 4294967296.0f);
+ if (chip & CHIP_FBI)
+ voodoo->params.startW = (int64_t)(tempif.f * 4294967296.0f);
+ break;
+
+ case SST_fdRdX: case SST_remap_fdRdX:
+ tempif.i = val;
+ voodoo->params.dRdX = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fdGdX: case SST_remap_fdGdX:
+ tempif.i = val;
+ voodoo->params.dGdX = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fdBdX: case SST_remap_fdBdX:
+ tempif.i = val;
+ voodoo->params.dBdX = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fdZdX: case SST_remap_fdZdX:
+ tempif.i = val;
+ voodoo->params.dZdX = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fdAdX: case SST_remap_fdAdX:
+ tempif.i = val;
+ voodoo->params.dAdX = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fdSdX: case SST_remap_fdSdX:
+ tempif.i = val;
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].dSdX = (int64_t)(tempif.f * 4294967296.0f);
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].dSdX = (int64_t)(tempif.f * 4294967296.0f);
+ break;
+ case SST_fdTdX: case SST_remap_fdTdX:
+ tempif.i = val;
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].dTdX = (int64_t)(tempif.f * 4294967296.0f);
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].dTdX = (int64_t)(tempif.f * 4294967296.0f);
+ break;
+ case SST_fdWdX: case SST_remap_fdWdX:
+ tempif.i = val;
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].dWdX = (int64_t)(tempif.f * 4294967296.0f);
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].dWdX = (int64_t)(tempif.f * 4294967296.0f);
+ if (chip & CHIP_FBI)
+ voodoo->params.dWdX = (int64_t)(tempif.f * 4294967296.0f);
+ break;
+
+ case SST_fdRdY: case SST_remap_fdRdY:
+ tempif.i = val;
+ voodoo->params.dRdY = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fdGdY: case SST_remap_fdGdY:
+ tempif.i = val;
+ voodoo->params.dGdY = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fdBdY: case SST_remap_fdBdY:
+ tempif.i = val;
+ voodoo->params.dBdY = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fdZdY: case SST_remap_fdZdY:
+ tempif.i = val;
+ voodoo->params.dZdY = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fdAdY: case SST_remap_fdAdY:
+ tempif.i = val;
+ voodoo->params.dAdY = (int32_t)(tempif.f * 4096.0f);
+ break;
+ case SST_fdSdY: case SST_remap_fdSdY:
+ tempif.i = val;
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].dSdY = (int64_t)(tempif.f * 4294967296.0f);
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].dSdY = (int64_t)(tempif.f * 4294967296.0f);
+ break;
+ case SST_fdTdY: case SST_remap_fdTdY:
+ tempif.i = val;
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].dTdY = (int64_t)(tempif.f * 4294967296.0f);
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].dTdY = (int64_t)(tempif.f * 4294967296.0f);
+ break;
+ case SST_fdWdY: case SST_remap_fdWdY:
+ tempif.i = val;
+ if (chip & CHIP_TREX0)
+ voodoo->params.tmu[0].dWdY = (int64_t)(tempif.f * 4294967296.0f);
+ if (chip & CHIP_TREX1)
+ voodoo->params.tmu[1].dWdY = (int64_t)(tempif.f * 4294967296.0f);
+ if (chip & CHIP_FBI)
+ voodoo->params.dWdY = (int64_t)(tempif.f * 4294967296.0f);
+ break;
+
+ case SST_ftriangleCMD:
+ voodoo->params.sign = val & (1 << 31);
+
+ if (voodoo->ncc_dirty[0])
+ voodoo_update_ncc(voodoo, 0);
+ if (voodoo->ncc_dirty[1])
+ voodoo_update_ncc(voodoo, 1);
+ voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0;
+
+ voodoo_queue_triangle(voodoo, &voodoo->params);
+
+ voodoo->cmd_read++;
+ break;
+
+ case SST_fbzColorPath:
+ voodoo->params.fbzColorPath = val;
+ voodoo->rgb_sel = val & 3;
+ break;
+
+ case SST_fogMode:
+ voodoo->params.fogMode = val;
+ break;
+ case SST_alphaMode:
+ voodoo->params.alphaMode = val;
+ break;
+ case SST_fbzMode:
+ voodoo->params.fbzMode = val;
+ voodoo_recalc(voodoo);
+ break;
+ case SST_lfbMode:
+ voodoo->lfbMode = val;
+ voodoo_recalc(voodoo);
+ break;
+
+ case SST_clipLeftRight:
+ if (voodoo->type >= VOODOO_2)
+ {
+ voodoo->params.clipRight = val & 0xfff;
+ voodoo->params.clipLeft = (val >> 16) & 0xfff;
+ }
+ else
+ {
+ voodoo->params.clipRight = val & 0x3ff;
+ voodoo->params.clipLeft = (val >> 16) & 0x3ff;
+ }
+ break;
+ case SST_clipLowYHighY:
+ if (voodoo->type >= VOODOO_2)
+ {
+ voodoo->params.clipHighY = val & 0xfff;
+ voodoo->params.clipLowY = (val >> 16) & 0xfff;
+ }
+ else
+ {
+ voodoo->params.clipHighY = val & 0x3ff;
+ voodoo->params.clipLowY = (val >> 16) & 0x3ff;
+ }
+ break;
+
+ case SST_nopCMD:
+ voodoo->cmd_read++;
+ voodoo->fbiPixelsIn = 0;
+ voodoo->fbiChromaFail = 0;
+ voodoo->fbiZFuncFail = 0;
+ voodoo->fbiAFuncFail = 0;
+ voodoo->fbiPixelsOut = 0;
+ break;
+ case SST_fastfillCMD:
+ voodoo_wait_for_render_thread_idle(voodoo);
+ voodoo_fastfill(voodoo, &voodoo->params);
+ voodoo->cmd_read++;
+ break;
+
+ case SST_fogColor:
+ voodoo->params.fogColor.r = (val >> 16) & 0xff;
+ voodoo->params.fogColor.g = (val >> 8) & 0xff;
+ voodoo->params.fogColor.b = val & 0xff;
+ break;
+
+ case SST_zaColor:
+ voodoo->params.zaColor = val;
+ break;
+ case SST_chromaKey:
+ voodoo->params.chromaKey_r = (val >> 16) & 0xff;
+ voodoo->params.chromaKey_g = (val >> 8) & 0xff;
+ voodoo->params.chromaKey_b = val & 0xff;
+ voodoo->params.chromaKey = val & 0xffffff;
+ break;
+ case SST_stipple:
+ voodoo->params.stipple = val;
+ break;
+ case SST_color0:
+ voodoo->params.color0 = val;
+ break;
+ case SST_color1:
+ voodoo->params.color1 = val;
+ break;
+
+ case SST_fogTable00: case SST_fogTable01: case SST_fogTable02: case SST_fogTable03:
+ case SST_fogTable04: case SST_fogTable05: case SST_fogTable06: case SST_fogTable07:
+ case SST_fogTable08: case SST_fogTable09: case SST_fogTable0a: case SST_fogTable0b:
+ case SST_fogTable0c: case SST_fogTable0d: case SST_fogTable0e: case SST_fogTable0f:
+ case SST_fogTable10: case SST_fogTable11: case SST_fogTable12: case SST_fogTable13:
+ case SST_fogTable14: case SST_fogTable15: case SST_fogTable16: case SST_fogTable17:
+ case SST_fogTable18: case SST_fogTable19: case SST_fogTable1a: case SST_fogTable1b:
+ case SST_fogTable1c: case SST_fogTable1d: case SST_fogTable1e: case SST_fogTable1f:
+ addr = (addr - SST_fogTable00) >> 1;
+ voodoo->params.fogTable[addr].dfog = val & 0xff;
+ voodoo->params.fogTable[addr].fog = (val >> 8) & 0xff;
+ voodoo->params.fogTable[addr+1].dfog = (val >> 16) & 0xff;
+ voodoo->params.fogTable[addr+1].fog = (val >> 24) & 0xff;
+ break;
+
+ case SST_clipLeftRight1:
+ if (voodoo->type >= VOODOO_BANSHEE)
+ {
+ voodoo->params.clipRight1 = val & 0xfff;
+ voodoo->params.clipLeft1 = (val >> 16) & 0xfff;
+ }
+ break;
+ case SST_clipTopBottom1:
+ if (voodoo->type >= VOODOO_BANSHEE)
+ {
+ voodoo->params.clipHighY1 = val & 0xfff;
+ voodoo->params.clipLowY1 = (val >> 16) & 0xfff;
+ }
+ break;
+
+ case SST_colBufferAddr:
+ if (voodoo->type >= VOODOO_BANSHEE)
+ {
+ voodoo->params.draw_offset = val & 0xfffff0;
+ voodoo->fb_write_offset = voodoo->params.draw_offset;
+// pclog("colorBufferAddr=%06x\n", voodoo->params.draw_offset);
+ }
+ break;
+ case SST_colBufferStride:
+ if (voodoo->type >= VOODOO_BANSHEE)
+ {
+ voodoo->col_tiled = val & (1 << 15);
+ voodoo->params.col_tiled = voodoo->col_tiled;
+ if (voodoo->col_tiled)
+ {
+ voodoo->row_width = (val & 0x7f) * 128*32;
+// pclog("colBufferStride tiled = %i bytes, tiled %08x\n", voodoo->row_width, val);
+ }
+ else
+ {
+ voodoo->row_width = val & 0x3fff;
+// pclog("colBufferStride linear = %i bytes, linear\n", voodoo->row_width);
+ }
+ voodoo->params.row_width = voodoo->row_width;
+ }
+ break;
+ case SST_auxBufferAddr:
+ if (voodoo->type >= VOODOO_BANSHEE)
+ {
+ voodoo->params.aux_offset = val & 0xfffff0;
+// pclog("auxBufferAddr=%06x\n", voodoo->params.aux_offset);
+ }
+ break;
+ case SST_auxBufferStride:
+ if (voodoo->type >= VOODOO_BANSHEE)
+ {
+ voodoo->aux_tiled = val & (1 << 15);
+ voodoo->params.aux_tiled = voodoo->aux_tiled;
+ if (voodoo->aux_tiled)
+ {
+ voodoo->aux_row_width = (val & 0x7f) * 128*32;
+// pclog("auxBufferStride tiled = %i bytes, tiled\n", voodoo->aux_row_width);
+ }
+ else
+ {
+ voodoo->aux_row_width = val & 0x3fff;
+// pclog("auxBufferStride linear = %i bytes, linear\n", voodoo->aux_row_width);
+ }
+ voodoo->params.aux_row_width = voodoo->aux_row_width;
+ }
+ break;
+
+ case SST_clutData:
+ voodoo->clutData[(val >> 24) & 0x3f].b = val & 0xff;
+ voodoo->clutData[(val >> 24) & 0x3f].g = (val >> 8) & 0xff;
+ voodoo->clutData[(val >> 24) & 0x3f].r = (val >> 16) & 0xff;
+ if (val & 0x20000000)
+ {
+ voodoo->clutData[(val >> 24) & 0x3f].b = 255;
+ voodoo->clutData[(val >> 24) & 0x3f].g = 255;
+ voodoo->clutData[(val >> 24) & 0x3f].r = 255;
+ }
+ voodoo->clutData_dirty = 1;
+ break;
+
+ case SST_sSetupMode:
+ voodoo->sSetupMode = val;
+ break;
+ case SST_sVx:
+ tempif.i = val;
+ voodoo->verts[3].sVx = tempif.f;
+// pclog("sVx[%i]=%f\n", voodoo->vertex_num, tempif.f);
+ break;
+ case SST_sVy:
+ tempif.i = val;
+ voodoo->verts[3].sVy = tempif.f;
+// pclog("sVy[%i]=%f\n", voodoo->vertex_num, tempif.f);
+ break;
+ case SST_sARGB:
+ voodoo->verts[3].sBlue = (float)(val & 0xff);
+ voodoo->verts[3].sGreen = (float)((val >> 8) & 0xff);
+ voodoo->verts[3].sRed = (float)((val >> 16) & 0xff);
+ voodoo->verts[3].sAlpha = (float)((val >> 24) & 0xff);
+ break;
+ case SST_sRed:
+ tempif.i = val;
+ voodoo->verts[3].sRed = tempif.f;
+ break;
+ case SST_sGreen:
+ tempif.i = val;
+ voodoo->verts[3].sGreen = tempif.f;
+ break;
+ case SST_sBlue:
+ tempif.i = val;
+ voodoo->verts[3].sBlue = tempif.f;
+ break;
+ case SST_sAlpha:
+ tempif.i = val;
+ voodoo->verts[3].sAlpha = tempif.f;
+ break;
+ case SST_sVz:
+ tempif.i = val;
+ voodoo->verts[3].sVz = tempif.f;
+ break;
+ case SST_sWb:
+ tempif.i = val;
+ voodoo->verts[3].sWb = tempif.f;
+ break;
+ case SST_sW0:
+ tempif.i = val;
+ voodoo->verts[3].sW0 = tempif.f;
+ break;
+ case SST_sS0:
+ tempif.i = val;
+ voodoo->verts[3].sS0 = tempif.f;
+ break;
+ case SST_sT0:
+ tempif.i = val;
+ voodoo->verts[3].sT0 = tempif.f;
+ break;
+ case SST_sW1:
+ tempif.i = val;
+ voodoo->verts[3].sW1 = tempif.f;
+ break;
+ case SST_sS1:
+ tempif.i = val;
+ voodoo->verts[3].sS1 = tempif.f;
+ break;
+ case SST_sT1:
+ tempif.i = val;
+ voodoo->verts[3].sT1 = tempif.f;
+ break;
+
+ case SST_sBeginTriCMD:
+// pclog("sBeginTriCMD %i %f\n", voodoo->vertex_num, voodoo->verts[4].sVx);
+ voodoo->verts[0] = voodoo->verts[3];
+ voodoo->verts[1] = voodoo->verts[3];
+ voodoo->verts[2] = voodoo->verts[3];
+ voodoo->vertex_next_age = 0;
+ voodoo->vertex_ages[0] = voodoo->vertex_next_age++;
+
+ voodoo->num_verticies = 1;
+ voodoo->cull_pingpong = 0;
+ break;
+ case SST_sDrawTriCMD:
+// pclog("sDrawTriCMD %i %i\n", voodoo->num_verticies, voodoo->sSetupMode & SETUPMODE_STRIP_MODE);
+ /*I'm not sure this is the vertex selection algorithm actually used in the 3dfx
+ chips, but this works with a number of games that switch between strip and fan
+ mode in the middle of a run (eg Black & White, Viper Racing)*/
+ if (voodoo->vertex_next_age < 3)
+ {
+ /*Fewer than three vertices already written, store in next slot*/
+ int vertex_nr = voodoo->vertex_next_age;
+
+ voodoo->verts[vertex_nr] = voodoo->verts[3];
+ voodoo->vertex_ages[vertex_nr] = voodoo->vertex_next_age++;
+ }
+ else
+ {
+ int vertex_nr = 0;
+
+ if (!(voodoo->sSetupMode & SETUPMODE_STRIP_MODE))
+ {
+ /*Strip - find oldest vertex*/
+ if ((voodoo->vertex_ages[0] < voodoo->vertex_ages[1]) &&
+ (voodoo->vertex_ages[0] < voodoo->vertex_ages[2]))
+ vertex_nr = 0;
+ else if ((voodoo->vertex_ages[1] < voodoo->vertex_ages[0]) &&
+ (voodoo->vertex_ages[1] < voodoo->vertex_ages[2]))
+ vertex_nr = 1;
+ else
+ vertex_nr = 2;
+ }
+ else
+ {
+ /*Fan - find second oldest vertex (ie pivot around oldest)*/
+ if ((voodoo->vertex_ages[1] < voodoo->vertex_ages[0]) &&
+ (voodoo->vertex_ages[0] < voodoo->vertex_ages[2]))
+ vertex_nr = 0;
+ else if ((voodoo->vertex_ages[2] < voodoo->vertex_ages[0]) &&
+ (voodoo->vertex_ages[0] < voodoo->vertex_ages[1]))
+ vertex_nr = 0;
+ else if ((voodoo->vertex_ages[0] < voodoo->vertex_ages[1]) &&
+ (voodoo->vertex_ages[1] < voodoo->vertex_ages[2]))
+ vertex_nr = 1;
+ else if ((voodoo->vertex_ages[2] < voodoo->vertex_ages[1]) &&
+ (voodoo->vertex_ages[1] < voodoo->vertex_ages[0]))
+ vertex_nr = 1;
+ else
+ vertex_nr = 2;
+ }
+ voodoo->verts[vertex_nr] = voodoo->verts[3];
+ voodoo->vertex_ages[vertex_nr] = voodoo->vertex_next_age++;
+ }
+
+ voodoo->num_verticies++;
+ if (voodoo->num_verticies == 3)
+ {
+// pclog("triangle_setup\n");
+ voodoo_triangle_setup(voodoo);
+ voodoo->cull_pingpong = !voodoo->cull_pingpong;
+
+ voodoo->num_verticies = 2;
+ }
+ break;
+
+ case SST_bltSrcBaseAddr:
+ voodoo->bltSrcBaseAddr = val & 0x3fffff;
+ break;
+ case SST_bltDstBaseAddr:
+// pclog("Write bltDstBaseAddr %08x\n", val);
+ voodoo->bltDstBaseAddr = val & 0x3fffff;
+ break;
+ case SST_bltXYStrides:
+ voodoo->bltSrcXYStride = val & 0xfff;
+ voodoo->bltDstXYStride = (val >> 16) & 0xfff;
+// pclog("Write bltXYStrides %08x\n", val);
+ break;
+ case SST_bltSrcChromaRange:
+ voodoo->bltSrcChromaRange = val;
+ voodoo->bltSrcChromaMinB = val & 0x1f;
+ voodoo->bltSrcChromaMinG = (val >> 5) & 0x3f;
+ voodoo->bltSrcChromaMinR = (val >> 11) & 0x1f;
+ voodoo->bltSrcChromaMaxB = (val >> 16) & 0x1f;
+ voodoo->bltSrcChromaMaxG = (val >> 21) & 0x3f;
+ voodoo->bltSrcChromaMaxR = (val >> 27) & 0x1f;
+ break;
+ case SST_bltDstChromaRange:
+ voodoo->bltDstChromaRange = val;
+ voodoo->bltDstChromaMinB = val & 0x1f;
+ voodoo->bltDstChromaMinG = (val >> 5) & 0x3f;
+ voodoo->bltDstChromaMinR = (val >> 11) & 0x1f;
+ voodoo->bltDstChromaMaxB = (val >> 16) & 0x1f;
+ voodoo->bltDstChromaMaxG = (val >> 21) & 0x3f;
+ voodoo->bltDstChromaMaxR = (val >> 27) & 0x1f;
+ break;
+ case SST_bltClipX:
+ voodoo->bltClipRight = val & 0xfff;
+ voodoo->bltClipLeft = (val >> 16) & 0xfff;
+ break;
+ case SST_bltClipY:
+ voodoo->bltClipHighY = val & 0xfff;
+ voodoo->bltClipLowY = (val >> 16) & 0xfff;
+ break;
+
+ case SST_bltSrcXY:
+ voodoo->bltSrcX = val & 0x7ff;
+ voodoo->bltSrcY = (val >> 16) & 0x7ff;
+ break;
+ case SST_bltDstXY:
+// pclog("Write bltDstXY %08x\n", val);
+ voodoo->bltDstX = val & 0x7ff;
+ voodoo->bltDstY = (val >> 16) & 0x7ff;
+ if (val & (1 << 31))
+ voodoo_v2_blit_start(voodoo);
+ break;
+ case SST_bltSize:
+// pclog("Write bltSize %08x\n", val);
+ voodoo->bltSizeX = val & 0xfff;
+ if (voodoo->bltSizeX & 0x800)
+ voodoo->bltSizeX |= 0xfffff000;
+ voodoo->bltSizeY = (val >> 16) & 0xfff;
+ if (voodoo->bltSizeY & 0x800)
+ voodoo->bltSizeY |= 0xfffff000;
+ if (val & (1 << 31))
+ voodoo_v2_blit_start(voodoo);
+ break;
+ case SST_bltRop:
+ voodoo->bltRop[0] = val & 0xf;
+ voodoo->bltRop[1] = (val >> 4) & 0xf;
+ voodoo->bltRop[2] = (val >> 8) & 0xf;
+ voodoo->bltRop[3] = (val >> 12) & 0xf;
+ break;
+ case SST_bltColor:
+// pclog("Write bltColor %08x\n", val);
+ voodoo->bltColorFg = val & 0xffff;
+ voodoo->bltColorBg = (val >> 16) & 0xffff;
+ break;
+
+ case SST_bltCommand:
+ voodoo->bltCommand = val;
+// pclog("Write bltCommand %08x\n", val);
+ if (val & (1 << 31))
+ voodoo_v2_blit_start(voodoo);
+ break;
+ case SST_bltData:
+ voodoo_v2_blit_data(voodoo, val);
+ break;
+
+ case SST_textureMode:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->params.textureMode[0] = val;
+ voodoo->params.tformat[0] = (val >> 8) & 0xf;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->params.textureMode[1] = val;
+ voodoo->params.tformat[1] = (val >> 8) & 0xf;
+ }
+ break;
+ case SST_tLOD:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->params.tLOD[0] = val;
+ voodoo_recalc_tex(voodoo, 0);
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->params.tLOD[1] = val;
+ voodoo_recalc_tex(voodoo, 1);
+ }
+ break;
+ case SST_tDetail:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->params.detail_max[0] = val & 0xff;
+ voodoo->params.detail_bias[0] = (val >> 8) & 0x3f;
+ voodoo->params.detail_scale[0] = (val >> 14) & 7;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->params.detail_max[1] = val & 0xff;
+ voodoo->params.detail_bias[1] = (val >> 8) & 0x3f;
+ voodoo->params.detail_scale[1] = (val >> 14) & 7;
+ }
+ break;
+ case SST_texBaseAddr:
+ if (chip & CHIP_TREX0)
+ {
+ if (voodoo->type >= VOODOO_BANSHEE)
+ voodoo->params.texBaseAddr[0] = val & 0xfffff0;
+ else
+ voodoo->params.texBaseAddr[0] = (val & 0x7ffff) << 3;
+// pclog("texBaseAddr = %08x %08x\n", voodoo->params.texBaseAddr[0], val);
+ voodoo_recalc_tex(voodoo, 0);
+ }
+ if (chip & CHIP_TREX1)
+ {
+ if (voodoo->type >= VOODOO_BANSHEE)
+ voodoo->params.texBaseAddr[1] = val & 0xfffff0;
+ else
+ voodoo->params.texBaseAddr[1] = (val & 0x7ffff) << 3;
+ voodoo_recalc_tex(voodoo, 1);
+ }
+ break;
+ case SST_texBaseAddr1:
+ if (chip & CHIP_TREX0)
+ {
+ if (voodoo->type >= VOODOO_BANSHEE)
+ voodoo->params.texBaseAddr1[0] = val & 0xfffff0;
+ else
+ voodoo->params.texBaseAddr1[0] = (val & 0x7ffff) << 3;
+ voodoo_recalc_tex(voodoo, 0);
+ }
+ if (chip & CHIP_TREX1)
+ {
+ if (voodoo->type >= VOODOO_BANSHEE)
+ voodoo->params.texBaseAddr1[1] = val & 0xfffff0;
+ else
+ voodoo->params.texBaseAddr1[1] = (val & 0x7ffff) << 3;
+ voodoo_recalc_tex(voodoo, 1);
+ }
+ break;
+ case SST_texBaseAddr2:
+ if (chip & CHIP_TREX0)
+ {
+ if (voodoo->type >= VOODOO_BANSHEE)
+ voodoo->params.texBaseAddr2[0] = val & 0xfffff0;
+ else
+ voodoo->params.texBaseAddr2[0] = (val & 0x7ffff) << 3;
+ voodoo_recalc_tex(voodoo, 0);
+ }
+ if (chip & CHIP_TREX1)
+ {
+ if (voodoo->type >= VOODOO_BANSHEE)
+ voodoo->params.texBaseAddr2[1] = val & 0xfffff0;
+ else
+ voodoo->params.texBaseAddr2[1] = (val & 0x7ffff) << 3;
+ voodoo_recalc_tex(voodoo, 1);
+ }
+ break;
+ case SST_texBaseAddr38:
+ if (chip & CHIP_TREX0)
+ {
+ if (voodoo->type >= VOODOO_BANSHEE)
+ voodoo->params.texBaseAddr38[0] = val & 0xfffff0;
+ else
+ voodoo->params.texBaseAddr38[0] = (val & 0x7ffff) << 3;
+ voodoo_recalc_tex(voodoo, 0);
+ }
+ if (chip & CHIP_TREX1)
+ {
+ if (voodoo->type >= VOODOO_BANSHEE)
+ voodoo->params.texBaseAddr38[1] = val & 0xfffff0;
+ else
+ voodoo->params.texBaseAddr38[1] = (val & 0x7ffff) << 3;
+ voodoo_recalc_tex(voodoo, 1);
+ }
+ break;
+
+ case SST_trexInit1:
+ if (chip & CHIP_TREX0)
+ voodoo->trexInit1[0] = val;
+ if (chip & CHIP_TREX1)
+ voodoo->trexInit1[1] = val;
+ break;
+
+ case SST_nccTable0_Y0:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][0].y[0] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][0].y[0] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ case SST_nccTable0_Y1:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][0].y[1] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][0].y[1] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ case SST_nccTable0_Y2:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][0].y[2] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][0].y[2] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ case SST_nccTable0_Y3:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][0].y[3] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][0].y[3] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+
+ case SST_nccTable0_I0:
+ if (!(val & (1 << 31)))
+ {
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][0].i[0] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][0].i[0] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ }
+ case SST_nccTable0_I2:
+ if (!(val & (1 << 31)))
+ {
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][0].i[2] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][0].i[2] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ }
+ case SST_nccTable0_Q0:
+ if (!(val & (1 << 31)))
+ {
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][0].q[0] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][0].q[0] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ }
+ case SST_nccTable0_Q2:
+ if (!(val & (1 << 31)))
+ {
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][0].i[2] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][0].i[2] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ }
+ if (val & (1 << 31))
+ {
+ int p = (val >> 23) & 0xfe;
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->palette[0][p].u = val | 0xff000000;
+ voodoo->palette_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->palette[1][p].u = val | 0xff000000;
+ voodoo->palette_dirty[1] = 1;
+ }
+ }
+ break;
+
+ case SST_nccTable0_I1:
+ if (!(val & (1 << 31)))
+ {
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][0].i[1] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][0].i[1] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ }
+ case SST_nccTable0_I3:
+ if (!(val & (1 << 31)))
+ {
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][0].i[3] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][0].i[3] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ }
+ case SST_nccTable0_Q1:
+ if (!(val & (1 << 31)))
+ {
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][0].q[1] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][0].q[1] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ }
+ case SST_nccTable0_Q3:
+ if (!(val & (1 << 31)))
+ {
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][0].q[3] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][0].q[3] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ }
+ if (val & (1 << 31))
+ {
+ int p = ((val >> 23) & 0xfe) | 0x01;
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->palette[0][p].u = val | 0xff000000;
+ voodoo->palette_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->palette[1][p].u = val | 0xff000000;
+ voodoo->palette_dirty[1] = 1;
+ }
+ }
+ break;
+
+ case SST_nccTable1_Y0:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][1].y[0] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][1].y[0] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ case SST_nccTable1_Y1:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][1].y[1] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][1].y[1] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ case SST_nccTable1_Y2:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][1].y[2] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][1].y[2] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ case SST_nccTable1_Y3:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][1].y[3] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][1].y[3] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ case SST_nccTable1_I0:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][1].i[0] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][1].i[0] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ case SST_nccTable1_I1:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][1].i[1] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][1].i[1] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ case SST_nccTable1_I2:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][1].i[2] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][1].i[2] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ case SST_nccTable1_I3:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][1].i[3] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][1].i[3] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ case SST_nccTable1_Q0:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][1].q[0] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][1].q[0] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ case SST_nccTable1_Q1:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][1].q[1] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][1].q[1] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ case SST_nccTable1_Q2:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][1].q[2] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][1].q[2] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+ case SST_nccTable1_Q3:
+ if (chip & CHIP_TREX0)
+ {
+ voodoo->nccTable[0][1].q[3] = val;
+ voodoo->ncc_dirty[0] = 1;
+ }
+ if (chip & CHIP_TREX1)
+ {
+ voodoo->nccTable[1][1].q[3] = val;
+ voodoo->ncc_dirty[1] = 1;
+ }
+ break;
+
+ case SST_userIntrCMD:
+ fatal("userIntrCMD write %08x from FIFO\n", val);
+ break;
+
+
+ case SST_leftOverlayBuf:
+ voodoo->leftOverlayBuf = val;
+ break;
+ }
+}
diff --git a/src/vid_voodoo_reg.h b/src/vid_voodoo_reg.h
new file mode 100644
index 0000000..f3a9418
--- /dev/null
+++ b/src/vid_voodoo_reg.h
@@ -0,0 +1 @@
+void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p);
diff --git a/src/vid_voodoo_regs.h b/src/vid_voodoo_regs.h
new file mode 100644
index 0000000..e99241f
--- /dev/null
+++ b/src/vid_voodoo_regs.h
@@ -0,0 +1,694 @@
+enum
+{
+ SST_status = 0x000,
+ SST_intrCtrl = 0x004,
+
+ SST_vertexAx = 0x008,
+ SST_vertexAy = 0x00c,
+ SST_vertexBx = 0x010,
+ SST_vertexBy = 0x014,
+ SST_vertexCx = 0x018,
+ SST_vertexCy = 0x01c,
+
+ SST_startR = 0x0020,
+ SST_startG = 0x0024,
+ SST_startB = 0x0028,
+ SST_startZ = 0x002c,
+ SST_startA = 0x0030,
+ SST_startS = 0x0034,
+ SST_startT = 0x0038,
+ SST_startW = 0x003c,
+
+ SST_dRdX = 0x0040,
+ SST_dGdX = 0x0044,
+ SST_dBdX = 0x0048,
+ SST_dZdX = 0x004c,
+ SST_dAdX = 0x0050,
+ SST_dSdX = 0x0054,
+ SST_dTdX = 0x0058,
+ SST_dWdX = 0x005c,
+
+ SST_dRdY = 0x0060,
+ SST_dGdY = 0x0064,
+ SST_dBdY = 0x0068,
+ SST_dZdY = 0x006c,
+ SST_dAdY = 0x0070,
+ SST_dSdY = 0x0074,
+ SST_dTdY = 0x0078,
+ SST_dWdY = 0x007c,
+
+ SST_triangleCMD = 0x0080,
+
+ SST_fvertexAx = 0x088,
+ SST_fvertexAy = 0x08c,
+ SST_fvertexBx = 0x090,
+ SST_fvertexBy = 0x094,
+ SST_fvertexCx = 0x098,
+ SST_fvertexCy = 0x09c,
+
+ SST_fstartR = 0x00a0,
+ SST_fstartG = 0x00a4,
+ SST_fstartB = 0x00a8,
+ SST_fstartZ = 0x00ac,
+ SST_fstartA = 0x00b0,
+ SST_fstartS = 0x00b4,
+ SST_fstartT = 0x00b8,
+ SST_fstartW = 0x00bc,
+
+ SST_fdRdX = 0x00c0,
+ SST_fdGdX = 0x00c4,
+ SST_fdBdX = 0x00c8,
+ SST_fdZdX = 0x00cc,
+ SST_fdAdX = 0x00d0,
+ SST_fdSdX = 0x00d4,
+ SST_fdTdX = 0x00d8,
+ SST_fdWdX = 0x00dc,
+
+ SST_fdRdY = 0x00e0,
+ SST_fdGdY = 0x00e4,
+ SST_fdBdY = 0x00e8,
+ SST_fdZdY = 0x00ec,
+ SST_fdAdY = 0x00f0,
+ SST_fdSdY = 0x00f4,
+ SST_fdTdY = 0x00f8,
+ SST_fdWdY = 0x00fc,
+
+ SST_ftriangleCMD = 0x0100,
+
+ SST_fbzColorPath = 0x104,
+ SST_fogMode = 0x108,
+
+ SST_alphaMode = 0x10c,
+ SST_fbzMode = 0x110,
+ SST_lfbMode = 0x114,
+
+ SST_clipLeftRight = 0x118,
+ SST_clipLowYHighY = 0x11c,
+
+ SST_nopCMD = 0x120,
+ SST_fastfillCMD = 0x124,
+ SST_swapbufferCMD = 0x128,
+
+ SST_fogColor = 0x12c,
+ SST_zaColor = 0x130,
+ SST_chromaKey = 0x134,
+
+ SST_userIntrCMD = 0x13c,
+ SST_stipple = 0x140,
+ SST_color0 = 0x144,
+ SST_color1 = 0x148,
+
+ SST_fbiPixelsIn = 0x14c,
+ SST_fbiChromaFail = 0x150,
+ SST_fbiZFuncFail = 0x154,
+ SST_fbiAFuncFail = 0x158,
+ SST_fbiPixelsOut = 0x15c,
+
+ SST_fogTable00 = 0x160,
+ SST_fogTable01 = 0x164,
+ SST_fogTable02 = 0x168,
+ SST_fogTable03 = 0x16c,
+ SST_fogTable04 = 0x170,
+ SST_fogTable05 = 0x174,
+ SST_fogTable06 = 0x178,
+ SST_fogTable07 = 0x17c,
+ SST_fogTable08 = 0x180,
+ SST_fogTable09 = 0x184,
+ SST_fogTable0a = 0x188,
+ SST_fogTable0b = 0x18c,
+ SST_fogTable0c = 0x190,
+ SST_fogTable0d = 0x194,
+ SST_fogTable0e = 0x198,
+ SST_fogTable0f = 0x19c,
+ SST_fogTable10 = 0x1a0,
+ SST_fogTable11 = 0x1a4,
+ SST_fogTable12 = 0x1a8,
+ SST_fogTable13 = 0x1ac,
+ SST_fogTable14 = 0x1b0,
+ SST_fogTable15 = 0x1b4,
+ SST_fogTable16 = 0x1b8,
+ SST_fogTable17 = 0x1bc,
+ SST_fogTable18 = 0x1c0,
+ SST_fogTable19 = 0x1c4,
+ SST_fogTable1a = 0x1c8,
+ SST_fogTable1b = 0x1cc,
+ SST_fogTable1c = 0x1d0,
+ SST_fogTable1d = 0x1d4,
+ SST_fogTable1e = 0x1d8,
+ SST_fogTable1f = 0x1dc,
+
+ SST_cmdFifoBaseAddr = 0x1e0,
+ SST_cmdFifoBump = 0x1e4,
+ SST_cmdFifoRdPtr = 0x1e8,
+ SST_cmdFifoAMin = 0x1ec,
+ SST_cmdFifoAMax = 0x1f0,
+ SST_cmdFifoDepth = 0x1f4,
+ SST_cmdFifoHoles = 0x1f8,
+
+ SST_colBufferAddr = 0x1ec, /*Banshee*/
+ SST_colBufferStride = 0x1f0, /*Banshee*/
+ SST_auxBufferAddr = 0x1f4, /*Banshee*/
+ SST_auxBufferStride = 0x1f8, /*Banshee*/
+
+ SST_clipLeftRight1 = 0x200, /*Banshee*/
+ SST_clipTopBottom1 = 0x204, /*Banshee*/
+
+ SST_fbiInit4 = 0x200,
+ SST_vRetrace = 0x204,
+ SST_backPorch = 0x208,
+ SST_videoDimensions = 0x20c,
+ SST_fbiInit0 = 0x210,
+ SST_fbiInit1 = 0x214,
+ SST_fbiInit2 = 0x218,
+ SST_fbiInit3 = 0x21c,
+ SST_hSync = 0x220,
+ SST_vSync = 0x224,
+ SST_clutData = 0x228,
+ SST_dacData = 0x22c,
+
+ SST_scrFilter = 0x230,
+
+ SST_hvRetrace = 0x240,
+ SST_fbiInit5 = 0x244,
+ SST_fbiInit6 = 0x248,
+ SST_fbiInit7 = 0x24c,
+
+ SST_swapPending = 0x24c, /*Banshee*/
+ SST_leftOverlayBuf = 0x250, /*Banshee*/
+
+ SST_sSetupMode = 0x260,
+ SST_sVx = 0x264,
+ SST_sVy = 0x268,
+ SST_sARGB = 0x26c,
+ SST_sRed = 0x270,
+ SST_sGreen = 0x274,
+ SST_sBlue = 0x278,
+ SST_sAlpha = 0x27c,
+ SST_sVz = 0x280,
+ SST_sWb = 0x284,
+ SST_sW0 = 0x288,
+ SST_sS0 = 0x28c,
+ SST_sT0 = 0x290,
+ SST_sW1 = 0x294,
+ SST_sS1 = 0x298,
+ SST_sT1 = 0x29c,
+
+ SST_sDrawTriCMD = 0x2a0,
+ SST_sBeginTriCMD = 0x2a4,
+
+ SST_bltSrcBaseAddr = 0x2c0,
+ SST_bltDstBaseAddr = 0x2c4,
+ SST_bltXYStrides = 0x2c8,
+ SST_bltSrcChromaRange = 0x2cc,
+ SST_bltDstChromaRange = 0x2d0,
+ SST_bltClipX = 0x2d4,
+ SST_bltClipY = 0x2d8,
+
+ SST_bltSrcXY = 0x2e0,
+ SST_bltDstXY = 0x2e4,
+ SST_bltSize = 0x2e8,
+ SST_bltRop = 0x2ec,
+ SST_bltColor = 0x2f0,
+
+ SST_bltCommand = 0x2f8,
+ SST_bltData = 0x2fc,
+
+ SST_textureMode = 0x300,
+ SST_tLOD = 0x304,
+ SST_tDetail = 0x308,
+ SST_texBaseAddr = 0x30c,
+ SST_texBaseAddr1 = 0x310,
+ SST_texBaseAddr2 = 0x314,
+ SST_texBaseAddr38 = 0x318,
+
+ SST_trexInit1 = 0x320,
+
+ SST_nccTable0_Y0 = 0x324,
+ SST_nccTable0_Y1 = 0x328,
+ SST_nccTable0_Y2 = 0x32c,
+ SST_nccTable0_Y3 = 0x330,
+ SST_nccTable0_I0 = 0x334,
+ SST_nccTable0_I1 = 0x338,
+ SST_nccTable0_I2 = 0x33c,
+ SST_nccTable0_I3 = 0x340,
+ SST_nccTable0_Q0 = 0x344,
+ SST_nccTable0_Q1 = 0x348,
+ SST_nccTable0_Q2 = 0x34c,
+ SST_nccTable0_Q3 = 0x350,
+
+ SST_nccTable1_Y0 = 0x354,
+ SST_nccTable1_Y1 = 0x358,
+ SST_nccTable1_Y2 = 0x35c,
+ SST_nccTable1_Y3 = 0x360,
+ SST_nccTable1_I0 = 0x364,
+ SST_nccTable1_I1 = 0x368,
+ SST_nccTable1_I2 = 0x36c,
+ SST_nccTable1_I3 = 0x370,
+ SST_nccTable1_Q0 = 0x374,
+ SST_nccTable1_Q1 = 0x378,
+ SST_nccTable1_Q2 = 0x37c,
+ SST_nccTable1_Q3 = 0x380,
+
+ SST_remap_status = 0x000 | 0x400,
+
+ SST_remap_vertexAx = 0x008 | 0x400,
+ SST_remap_vertexAy = 0x00c | 0x400,
+ SST_remap_vertexBx = 0x010 | 0x400,
+ SST_remap_vertexBy = 0x014 | 0x400,
+ SST_remap_vertexCx = 0x018 | 0x400,
+ SST_remap_vertexCy = 0x01c | 0x400,
+
+ SST_remap_startR = 0x0020 | 0x400,
+ SST_remap_startG = 0x002c | 0x400,
+ SST_remap_startB = 0x0038 | 0x400,
+ SST_remap_startZ = 0x0044 | 0x400,
+ SST_remap_startA = 0x0050 | 0x400,
+ SST_remap_startS = 0x005c | 0x400,
+ SST_remap_startT = 0x0068 | 0x400,
+ SST_remap_startW = 0x0074 | 0x400,
+
+ SST_remap_dRdX = 0x0024 | 0x400,
+ SST_remap_dGdX = 0x0030 | 0x400,
+ SST_remap_dBdX = 0x003c | 0x400,
+ SST_remap_dZdX = 0x0048 | 0x400,
+ SST_remap_dAdX = 0x0054 | 0x400,
+ SST_remap_dSdX = 0x0060 | 0x400,
+ SST_remap_dTdX = 0x006c | 0x400,
+ SST_remap_dWdX = 0x0078 | 0x400,
+
+ SST_remap_dRdY = 0x0028 | 0x400,
+ SST_remap_dGdY = 0x0034 | 0x400,
+ SST_remap_dBdY = 0x0040 | 0x400,
+ SST_remap_dZdY = 0x004c | 0x400,
+ SST_remap_dAdY = 0x0058 | 0x400,
+ SST_remap_dSdY = 0x0064 | 0x400,
+ SST_remap_dTdY = 0x0070 | 0x400,
+ SST_remap_dWdY = 0x007c | 0x400,
+
+ SST_remap_triangleCMD = 0x0080 | 0x400,
+
+ SST_remap_fvertexAx = 0x088 | 0x400,
+ SST_remap_fvertexAy = 0x08c | 0x400,
+ SST_remap_fvertexBx = 0x090 | 0x400,
+ SST_remap_fvertexBy = 0x094 | 0x400,
+ SST_remap_fvertexCx = 0x098 | 0x400,
+ SST_remap_fvertexCy = 0x09c | 0x400,
+
+ SST_remap_fstartR = 0x00a0 | 0x400,
+ SST_remap_fstartG = 0x00ac | 0x400,
+ SST_remap_fstartB = 0x00b8 | 0x400,
+ SST_remap_fstartZ = 0x00c4 | 0x400,
+ SST_remap_fstartA = 0x00d0 | 0x400,
+ SST_remap_fstartS = 0x00dc | 0x400,
+ SST_remap_fstartT = 0x00e8 | 0x400,
+ SST_remap_fstartW = 0x00f4 | 0x400,
+
+ SST_remap_fdRdX = 0x00a4 | 0x400,
+ SST_remap_fdGdX = 0x00b0 | 0x400,
+ SST_remap_fdBdX = 0x00bc | 0x400,
+ SST_remap_fdZdX = 0x00c8 | 0x400,
+ SST_remap_fdAdX = 0x00d4 | 0x400,
+ SST_remap_fdSdX = 0x00e0 | 0x400,
+ SST_remap_fdTdX = 0x00ec | 0x400,
+ SST_remap_fdWdX = 0x00f8 | 0x400,
+
+ SST_remap_fdRdY = 0x00a8 | 0x400,
+ SST_remap_fdGdY = 0x00b4 | 0x400,
+ SST_remap_fdBdY = 0x00c0 | 0x400,
+ SST_remap_fdZdY = 0x00cc | 0x400,
+ SST_remap_fdAdY = 0x00d8 | 0x400,
+ SST_remap_fdSdY = 0x00e4 | 0x400,
+ SST_remap_fdTdY = 0x00f0 | 0x400,
+ SST_remap_fdWdY = 0x00fc | 0x400,
+};
+
+enum
+{
+ LFB_WRITE_FRONT = 0x0000,
+ LFB_WRITE_BACK = 0x0010,
+ LFB_WRITE_MASK = 0x0030
+};
+
+enum
+{
+ LFB_READ_FRONT = 0x0000,
+ LFB_READ_BACK = 0x0040,
+ LFB_READ_AUX = 0x0080,
+ LFB_READ_MASK = 0x00c0
+};
+
+enum
+{
+ LFB_FORMAT_RGB565 = 0,
+ LFB_FORMAT_RGB555 = 1,
+ LFB_FORMAT_ARGB1555 = 2,
+ LFB_FORMAT_ARGB8888 = 5,
+ LFB_FORMAT_DEPTH = 15,
+ LFB_FORMAT_MASK = 15
+};
+
+enum
+{
+ LFB_WRITE_COLOUR = 1,
+ LFB_WRITE_DEPTH = 2
+};
+
+enum
+{
+ FBZ_CHROMAKEY = (1 << 1),
+ FBZ_W_BUFFER = (1 << 3),
+ FBZ_DEPTH_ENABLE = (1 << 4),
+
+ FBZ_DITHER = (1 << 8),
+ FBZ_RGB_WMASK = (1 << 9),
+ FBZ_DEPTH_WMASK = (1 << 10),
+ FBZ_DITHER_2x2 = (1 << 11),
+
+ FBZ_DRAW_FRONT = 0x0000,
+ FBZ_DRAW_BACK = 0x4000,
+ FBZ_DRAW_MASK = 0xc000,
+
+ FBZ_DEPTH_BIAS = (1 << 16),
+
+ FBZ_DITHER_SUB = (1 << 19),
+ FBZ_DEPTH_SOURCE = (1 << 20),
+
+ FBZ_PARAM_ADJUST = (1 << 26)
+};
+
+enum
+{
+ TEX_RGB332 = 0x0,
+ TEX_Y4I2Q2 = 0x1,
+ TEX_A8 = 0x2,
+ TEX_I8 = 0x3,
+ TEX_AI8 = 0x4,
+ TEX_PAL8 = 0x5,
+ TEX_APAL8 = 0x6,
+ TEX_ARGB8332 = 0x8,
+ TEX_A8Y4I2Q2 = 0x9,
+ TEX_R5G6B5 = 0xa,
+ TEX_ARGB1555 = 0xb,
+ TEX_ARGB4444 = 0xc,
+ TEX_A8I8 = 0xd,
+ TEX_APAL88 = 0xe
+};
+
+enum
+{
+ TEXTUREMODE_NCC_SEL = (1 << 5),
+ TEXTUREMODE_TCLAMPS = (1 << 6),
+ TEXTUREMODE_TCLAMPT = (1 << 7),
+ TEXTUREMODE_TRILINEAR = (1 << 30)
+};
+
+enum
+{
+ FBIINIT0_VGA_PASS = 1,
+ FBIINIT0_GRAPHICS_RESET = (1 << 1)
+};
+
+enum
+{
+ FBIINIT1_MULTI_SST = (1 << 2), /*Voodoo Graphics only*/
+ FBIINIT1_VIDEO_RESET = (1 << 8),
+ FBIINIT1_SLI_ENABLE = (1 << 23)
+};
+
+enum
+{
+ FBIINIT2_SWAP_ALGORITHM_MASK = (3 << 9)
+};
+
+enum
+{
+ FBIINIT2_SWAP_ALGORITHM_DAC_VSYNC = (0 << 9),
+ FBIINIT2_SWAP_ALGORITHM_DAC_DATA = (1 << 9),
+ FBIINIT2_SWAP_ALGORITHM_PCI_FIFO_STALL = (2 << 9),
+ FBIINIT2_SWAP_ALGORITHM_SLI_SYNC = (3 << 9)
+};
+
+enum
+{
+ FBIINIT3_REMAP = 1
+};
+
+enum
+{
+ FBIINIT5_MULTI_CVG = (1 << 14)
+};
+
+enum
+{
+ FBIINIT7_CMDFIFO_ENABLE = (1 << 8)
+};
+
+enum
+{
+ CC_LOCALSELECT_ITER_RGB = 0,
+ CC_LOCALSELECT_TEX = 1,
+ CC_LOCALSELECT_COLOR1 = 2,
+ CC_LOCALSELECT_LFB = 3
+};
+
+enum
+{
+ CCA_LOCALSELECT_ITER_A = 0,
+ CCA_LOCALSELECT_COLOR0 = 1,
+ CCA_LOCALSELECT_ITER_Z = 2
+};
+
+enum
+{
+ C_SEL_ITER_RGB = 0,
+ C_SEL_TEX = 1,
+ C_SEL_COLOR1 = 2,
+ C_SEL_LFB = 3
+};
+
+enum
+{
+ A_SEL_ITER_A = 0,
+ A_SEL_TEX = 1,
+ A_SEL_COLOR1 = 2,
+ A_SEL_LFB = 3
+};
+
+enum
+{
+ CC_MSELECT_ZERO = 0,
+ CC_MSELECT_CLOCAL = 1,
+ CC_MSELECT_AOTHER = 2,
+ CC_MSELECT_ALOCAL = 3,
+ CC_MSELECT_TEX = 4,
+ CC_MSELECT_TEXRGB = 5
+};
+
+enum
+{
+ CCA_MSELECT_ZERO = 0,
+ CCA_MSELECT_ALOCAL = 1,
+ CCA_MSELECT_AOTHER = 2,
+ CCA_MSELECT_ALOCAL2 = 3,
+ CCA_MSELECT_TEX = 4
+};
+
+enum
+{
+ TC_MSELECT_ZERO = 0,
+ TC_MSELECT_CLOCAL = 1,
+ TC_MSELECT_AOTHER = 2,
+ TC_MSELECT_ALOCAL = 3,
+ TC_MSELECT_DETAIL = 4,
+ TC_MSELECT_LOD_FRAC = 5
+};
+
+enum
+{
+ TCA_MSELECT_ZERO = 0,
+ TCA_MSELECT_CLOCAL = 1,
+ TCA_MSELECT_AOTHER = 2,
+ TCA_MSELECT_ALOCAL = 3,
+ TCA_MSELECT_DETAIL = 4,
+ TCA_MSELECT_LOD_FRAC = 5
+};
+
+enum
+{
+ CC_ADD_CLOCAL = 1,
+ CC_ADD_ALOCAL = 2
+};
+
+enum
+{
+ CCA_ADD_CLOCAL = 1,
+ CCA_ADD_ALOCAL = 2
+};
+
+enum
+{
+ AFUNC_AZERO = 0x0,
+ AFUNC_ASRC_ALPHA = 0x1,
+ AFUNC_A_COLOR = 0x2,
+ AFUNC_ADST_ALPHA = 0x3,
+ AFUNC_AONE = 0x4,
+ AFUNC_AOMSRC_ALPHA = 0x5,
+ AFUNC_AOM_COLOR = 0x6,
+ AFUNC_AOMDST_ALPHA = 0x7,
+ AFUNC_ASATURATE = 0xf
+};
+
+enum
+{
+ AFUNC_ACOLORBEFOREFOG = 0xf
+};
+
+enum
+{
+ AFUNC_NEVER = 0,
+ AFUNC_LESSTHAN = 1,
+ AFUNC_EQUAL = 2,
+ AFUNC_LESSTHANEQUAL = 3,
+ AFUNC_GREATERTHAN = 4,
+ AFUNC_NOTEQUAL = 5,
+ AFUNC_GREATERTHANEQUAL = 6,
+ AFUNC_ALWAYS = 7
+};
+
+enum
+{
+ DEPTHOP_NEVER = 0,
+ DEPTHOP_LESSTHAN = 1,
+ DEPTHOP_EQUAL = 2,
+ DEPTHOP_LESSTHANEQUAL = 3,
+ DEPTHOP_GREATERTHAN = 4,
+ DEPTHOP_NOTEQUAL = 5,
+ DEPTHOP_GREATERTHANEQUAL = 6,
+ DEPTHOP_ALWAYS = 7
+};
+
+enum
+{
+ FOG_ENABLE = 0x01,
+ FOG_ADD = 0x02,
+ FOG_MULT = 0x04,
+ FOG_ALPHA = 0x08,
+ FOG_Z = 0x10,
+ FOG_W = 0x18,
+ FOG_CONSTANT = 0x20
+};
+
+enum
+{
+ LOD_ODD = (1 << 18),
+ LOD_SPLIT = (1 << 19),
+ LOD_S_IS_WIDER = (1 << 20),
+ LOD_TMULTIBASEADDR = (1 << 24),
+ LOD_TMIRROR_S = (1 << 28),
+ LOD_TMIRROR_T = (1 << 29)
+};
+enum
+{
+ CMD_INVALID = 0,
+ CMD_DRAWTRIANGLE,
+ CMD_FASTFILL,
+ CMD_SWAPBUF
+};
+
+enum
+{
+ FBZCP_TEXTURE_ENABLED = (1 << 27)
+};
+
+enum
+{
+ BLTCMD_SRC_TILED = (1 << 14),
+ BLTCMD_DST_TILED = (1 << 15)
+};
+
+enum
+{
+ INITENABLE_SLI_MASTER_SLAVE = (1 << 11)
+};
+
+enum
+{
+ SETUPMODE_RGB = (1 << 0),
+ SETUPMODE_ALPHA = (1 << 1),
+ SETUPMODE_Z = (1 << 2),
+ SETUPMODE_Wb = (1 << 3),
+ SETUPMODE_W0 = (1 << 4),
+ SETUPMODE_S0_T0 = (1 << 5),
+ SETUPMODE_W1 = (1 << 6),
+ SETUPMODE_S1_T1 = (1 << 7),
+
+ SETUPMODE_STRIP_MODE = (1 << 16),
+ SETUPMODE_CULLING_ENABLE = (1 << 17),
+ SETUPMODE_CULLING_SIGN = (1 << 18),
+ SETUPMODE_DISABLE_PINGPONG = (1 << 19)
+};
+
+#define TEXTUREMODE_MASK 0x3ffff000
+#define TEXTUREMODE_PASSTHROUGH 0
+
+#define TEXTUREMODE_LOCAL_MASK 0x00643000
+#define TEXTUREMODE_LOCAL 0x00241000
+
+
+#define SLI_ENABLED (voodoo->fbiInit1 & FBIINIT1_SLI_ENABLE)
+#define TRIPLE_BUFFER ((voodoo->fbiInit2 & 0x10) || (voodoo->fbiInit5 & 0x600) == 0x400)
+
+
+#define _rgb_sel ( params->fbzColorPath & 3)
+#define a_sel ( (params->fbzColorPath >> 2) & 3)
+#define cc_localselect ( params->fbzColorPath & (1 << 4))
+#define cca_localselect ( (params->fbzColorPath >> 5) & 3)
+#define cc_localselect_override ( params->fbzColorPath & (1 << 7))
+#define cc_zero_other ( params->fbzColorPath & (1 << 8))
+#define cc_sub_clocal ( params->fbzColorPath & (1 << 9))
+#define cc_mselect ( (params->fbzColorPath >> 10) & 7)
+#define cc_reverse_blend ( params->fbzColorPath & (1 << 13))
+#define cc_add ( (params->fbzColorPath >> 14) & 3)
+#define cc_add_alocal ( params->fbzColorPath & (1 << 15))
+#define cc_invert_output ( params->fbzColorPath & (1 << 16))
+#define cca_zero_other ( params->fbzColorPath & (1 << 17))
+#define cca_sub_clocal ( params->fbzColorPath & (1 << 18))
+#define cca_mselect ( (params->fbzColorPath >> 19) & 7)
+#define cca_reverse_blend ( params->fbzColorPath & (1 << 22))
+#define cca_add ( (params->fbzColorPath >> 23) & 3)
+#define cca_invert_output ( params->fbzColorPath & (1 << 25))
+#define tc_zero_other (params->textureMode[0] & (1 << 12))
+#define tc_sub_clocal (params->textureMode[0] & (1 << 13))
+#define tc_mselect ((params->textureMode[0] >> 14) & 7)
+#define tc_reverse_blend (params->textureMode[0] & (1 << 17))
+#define tc_add_clocal (params->textureMode[0] & (1 << 18))
+#define tc_add_alocal (params->textureMode[0] & (1 << 19))
+#define tc_invert_output (params->textureMode[0] & (1 << 20))
+#define tca_zero_other (params->textureMode[0] & (1 << 21))
+#define tca_sub_clocal (params->textureMode[0] & (1 << 22))
+#define tca_mselect ((params->textureMode[0] >> 23) & 7)
+#define tca_reverse_blend (params->textureMode[0] & (1 << 26))
+#define tca_add_clocal (params->textureMode[0] & (1 << 27))
+#define tca_add_alocal (params->textureMode[0] & (1 << 28))
+#define tca_invert_output (params->textureMode[0] & (1 << 29))
+
+#define tc_sub_clocal_1 (params->textureMode[1] & (1 << 13))
+#define tc_mselect_1 ((params->textureMode[1] >> 14) & 7)
+#define tc_reverse_blend_1 (params->textureMode[1] & (1 << 17))
+#define tc_add_clocal_1 (params->textureMode[1] & (1 << 18))
+#define tc_add_alocal_1 (params->textureMode[1] & (1 << 19))
+#define tca_sub_clocal_1 (params->textureMode[1] & (1 << 22))
+#define tca_mselect_1 ((params->textureMode[1] >> 23) & 7)
+#define tca_reverse_blend_1 (params->textureMode[1] & (1 << 26))
+#define tca_add_clocal_1 (params->textureMode[1] & (1 << 27))
+#define tca_add_alocal_1 (params->textureMode[1] & (1 << 28))
+
+#define src_afunc ( (params->alphaMode >> 8) & 0xf)
+#define dest_afunc ( (params->alphaMode >> 12) & 0xf)
+#define alpha_func ( (params->alphaMode >> 1) & 7)
+#define a_ref ( params->alphaMode >> 24)
+#define depth_op ( (params->fbzMode >> 5) & 7)
+#define dither ( params->fbzMode & FBZ_DITHER)
+#define dither2x2 (params->fbzMode & FBZ_DITHER_2x2)
+#define dithersub (params->fbzMode & FBZ_DITHER_SUB)
+
diff --git a/src/vid_voodoo_render.c b/src/vid_voodoo_render.c
new file mode 100644
index 0000000..420e396
--- /dev/null
+++ b/src/vid_voodoo_render.c
@@ -0,0 +1,1655 @@
+#include
+#include
+#include "ibm.h"
+#include "device.h"
+#include "mem.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_svga.h"
+#include "vid_voodoo.h"
+#include "vid_voodoo_common.h"
+#include "vid_voodoo_dither.h"
+#include "vid_voodoo_regs.h"
+#include "vid_voodoo_render.h"
+#include "vid_voodoo_texture.h"
+
+typedef struct voodoo_state_t
+{
+ int xstart, xend, xdir;
+ uint32_t base_r, base_g, base_b, base_a, base_z;
+ struct
+ {
+ int64_t base_s, base_t, base_w;
+ int lod;
+ } tmu[2];
+ int64_t base_w;
+ int lod;
+ int lod_min[2], lod_max[2];
+ int dx1, dx2;
+ int y, yend, ydir;
+ int32_t dxAB, dxAC, dxBC;
+ int tex_b[2], tex_g[2], tex_r[2], tex_a[2];
+ int tex_s, tex_t;
+ int clamp_s[2], clamp_t[2];
+
+ int32_t vertexAx, vertexAy, vertexBx, vertexBy, vertexCx, vertexCy;
+
+ uint32_t *tex[2][LOD_MAX+1];
+ int tformat;
+
+ int *tex_w_mask[2];
+ int *tex_h_mask[2];
+ int *tex_shift[2];
+ int *tex_lod[2];
+
+ uint16_t *fb_mem, *aux_mem;
+
+ int32_t ib, ig, ir, ia;
+ int32_t z;
+
+ int32_t new_depth;
+
+ int64_t tmu0_s, tmu0_t;
+ int64_t tmu0_w;
+ int64_t tmu1_s, tmu1_t;
+ int64_t tmu1_w;
+ int64_t w;
+
+ int pixel_count, texel_count;
+ int x, x2, x_tiled;
+
+ uint32_t w_depth;
+
+ float log_temp;
+ uint32_t ebp_store;
+ uint32_t texBaseAddr;
+
+ int lod_frac[2];
+} voodoo_state_t;
+
+static int voodoo_output = 0;
+
+static uint8_t logtable[256] =
+{
+ 0x00,0x01,0x02,0x04,0x05,0x07,0x08,0x09,0x0b,0x0c,0x0e,0x0f,0x10,0x12,0x13,0x15,
+ 0x16,0x17,0x19,0x1a,0x1b,0x1d,0x1e,0x1f,0x21,0x22,0x23,0x25,0x26,0x27,0x28,0x2a,
+ 0x2b,0x2c,0x2e,0x2f,0x30,0x31,0x33,0x34,0x35,0x36,0x38,0x39,0x3a,0x3b,0x3d,0x3e,
+ 0x3f,0x40,0x41,0x43,0x44,0x45,0x46,0x47,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x50,0x51,
+ 0x52,0x53,0x54,0x55,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x60,0x61,0x62,0x63,
+ 0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,
+ 0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x83,0x84,0x85,
+ 0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,
+ 0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,0xa0,0xa1,0xa2,0xa2,0xa3,
+ 0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xad,0xae,0xaf,0xb0,0xb1,0xb2,
+ 0xb3,0xb4,0xb5,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbc,0xbd,0xbe,0xbf,0xc0,
+ 0xc1,0xc2,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xcd,
+ 0xce,0xcf,0xd0,0xd1,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd6,0xd7,0xd8,0xd9,0xda,0xda,
+ 0xdb,0xdc,0xdd,0xde,0xde,0xdf,0xe0,0xe1,0xe1,0xe2,0xe3,0xe4,0xe5,0xe5,0xe6,0xe7,
+ 0xe8,0xe8,0xe9,0xea,0xeb,0xeb,0xec,0xed,0xee,0xef,0xef,0xf0,0xf1,0xf2,0xf2,0xf3,
+ 0xf4,0xf5,0xf5,0xf6,0xf7,0xf7,0xf8,0xf9,0xfa,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff
+};
+
+static inline int fastlog(uint64_t val)
+{
+ uint64_t oldval = val;
+ int exp = 63;
+ int frac;
+
+ if (!val || val & (1ULL << 63))
+ return 0x80000000;
+
+ if (!(val & 0xffffffff00000000))
+ {
+ exp -= 32;
+ val <<= 32;
+ }
+ if (!(val & 0xffff000000000000))
+ {
+ exp -= 16;
+ val <<= 16;
+ }
+ if (!(val & 0xff00000000000000))
+ {
+ exp -= 8;
+ val <<= 8;
+ }
+ if (!(val & 0xf000000000000000))
+ {
+ exp -= 4;
+ val <<= 4;
+ }
+ if (!(val & 0xc000000000000000))
+ {
+ exp -= 2;
+ val <<= 2;
+ }
+ if (!(val & 0x8000000000000000))
+ {
+ exp -= 1;
+ val <<= 1;
+ }
+
+ if (exp >= 8)
+ frac = (oldval >> (exp - 8)) & 0xff;
+ else
+ frac = (oldval << (8 - exp)) & 0xff;
+
+ return (exp << 8) | logtable[frac];
+}
+
+static inline int voodoo_fls(uint16_t val)
+{
+ int num = 0;
+
+//pclog("fls(%04x) = ", val);
+ if (!(val & 0xff00))
+ {
+ num += 8;
+ val <<= 8;
+ }
+ if (!(val & 0xf000))
+ {
+ num += 4;
+ val <<= 4;
+ }
+ if (!(val & 0xc000))
+ {
+ num += 2;
+ val <<= 2;
+ }
+ if (!(val & 0x8000))
+ {
+ num += 1;
+ val <<= 1;
+ }
+//pclog("%i %04x\n", num, val);
+ return num;
+}
+
+typedef struct voodoo_texture_state_t
+{
+ int s, t;
+ int w_mask, h_mask;
+ int tex_shift;
+} voodoo_texture_state_t;
+
+static inline void tex_read(voodoo_state_t *state, voodoo_texture_state_t *texture_state, int tmu)
+{
+ uint32_t dat;
+
+ if (texture_state->s & ~texture_state->w_mask)
+ {
+ if (state->clamp_s[tmu])
+ {
+ if (texture_state->s < 0)
+ texture_state->s = 0;
+ if (texture_state->s > texture_state->w_mask)
+ texture_state->s = texture_state->w_mask;
+ }
+ else
+ texture_state->s &= texture_state->w_mask;
+ }
+ if (texture_state->t & ~texture_state->h_mask)
+ {
+ if (state->clamp_t[tmu])
+ {
+ if (texture_state->t < 0)
+ texture_state->t = 0;
+ if (texture_state->t > texture_state->h_mask)
+ texture_state->t = texture_state->h_mask;
+ }
+ else
+ texture_state->t &= texture_state->h_mask;
+ }
+
+ dat = state->tex[tmu][state->lod][texture_state->s + (texture_state->t << texture_state->tex_shift)];
+
+ state->tex_b[tmu] = dat & 0xff;
+ state->tex_g[tmu] = (dat >> 8) & 0xff;
+ state->tex_r[tmu] = (dat >> 16) & 0xff;
+ state->tex_a[tmu] = (dat >> 24) & 0xff;
+}
+
+#define LOW4(x) ((x & 0x0f) | ((x & 0x0f) << 4))
+#define HIGH4(x) ((x & 0xf0) | ((x & 0xf0) >> 4))
+
+static inline void tex_read_4(voodoo_state_t *state, voodoo_texture_state_t *texture_state, int s, int t, int *d, int tmu, int x)
+{
+ rgba_u dat[4];
+
+ if (((s | (s + 1)) & ~texture_state->w_mask) || ((t | (t + 1)) & ~texture_state->h_mask))
+ {
+ int c;
+ for (c = 0; c < 4; c++)
+ {
+ int _s = s + (c & 1);
+ int _t = t + ((c & 2) >> 1);
+
+ if (_s & ~texture_state->w_mask)
+ {
+ if (state->clamp_s[tmu])
+ {
+ if (_s < 0)
+ _s = 0;
+ if (_s > texture_state->w_mask)
+ _s = texture_state->w_mask;
+ }
+ else
+ _s &= texture_state->w_mask;
+ }
+ if (_t & ~texture_state->h_mask)
+ {
+ if (state->clamp_t[tmu])
+ {
+ if (_t < 0)
+ _t = 0;
+ if (_t > texture_state->h_mask)
+ _t = texture_state->h_mask;
+ }
+ else
+ _t &= texture_state->h_mask;
+ }
+ dat[c].u = state->tex[tmu][state->lod][_s + (_t << texture_state->tex_shift)];
+ }
+ }
+ else
+ {
+ dat[0].u = state->tex[tmu][state->lod][s + (t << texture_state->tex_shift)];
+ dat[1].u = state->tex[tmu][state->lod][s + 1 + (t << texture_state->tex_shift)];
+ dat[2].u = state->tex[tmu][state->lod][s + ((t + 1) << texture_state->tex_shift)];
+ dat[3].u = state->tex[tmu][state->lod][s + 1 + ((t + 1) << texture_state->tex_shift)];
+ }
+
+ state->tex_r[tmu] = (dat[0].rgba.r * d[0] + dat[1].rgba.r * d[1] + dat[2].rgba.r * d[2] + dat[3].rgba.r * d[3]) >> 8;
+ state->tex_g[tmu] = (dat[0].rgba.g * d[0] + dat[1].rgba.g * d[1] + dat[2].rgba.g * d[2] + dat[3].rgba.g * d[3]) >> 8;
+ state->tex_b[tmu] = (dat[0].rgba.b * d[0] + dat[1].rgba.b * d[1] + dat[2].rgba.b * d[2] + dat[3].rgba.b * d[3]) >> 8;
+ state->tex_a[tmu] = (dat[0].rgba.a * d[0] + dat[1].rgba.a * d[1] + dat[2].rgba.a * d[2] + dat[3].rgba.a * d[3]) >> 8;
+}
+
+static inline void voodoo_get_texture(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int tmu, int x)
+{
+ voodoo_texture_state_t texture_state;
+ int d[4];
+ int s, t;
+ int tex_lod = state->tex_lod[tmu][state->lod];
+
+ texture_state.w_mask = state->tex_w_mask[tmu][state->lod];
+ texture_state.h_mask = state->tex_h_mask[tmu][state->lod];
+ texture_state.tex_shift = 8 - tex_lod;
+
+ if (params->tLOD[tmu] & LOD_TMIRROR_S)
+ {
+ if (state->tex_s & 0x1000)
+ state->tex_s = ~state->tex_s;
+ }
+ if (params->tLOD[tmu] & LOD_TMIRROR_T)
+ {
+ if (state->tex_t & 0x1000)
+ state->tex_t = ~state->tex_t;
+ }
+
+ if (voodoo->bilinear_enabled && params->textureMode[tmu] & 6)
+ {
+ int _ds, dt;
+
+ state->tex_s -= 1 << (3+tex_lod);
+ state->tex_t -= 1 << (3+tex_lod);
+
+ s = state->tex_s >> tex_lod;
+ t = state->tex_t >> tex_lod;
+
+ _ds = s & 0xf;
+ dt = t & 0xf;
+
+ s >>= 4;
+ t >>= 4;
+//if (x == 80)
+//if (voodoo_output)
+// pclog("s=%08x t=%08x _ds=%02x _dt=%02x\n", s, t, _ds, dt);
+ d[0] = (16 - _ds) * (16 - dt);
+ d[1] = _ds * (16 - dt);
+ d[2] = (16 - _ds) * dt;
+ d[3] = _ds * dt;
+
+// texture_state.s = s;
+// texture_state.t = t;
+ tex_read_4(state, &texture_state, s, t, d, tmu, x);
+
+
+/* state->tex_r = (tex_samples[0].rgba.r * d[0] + tex_samples[1].rgba.r * d[1] + tex_samples[2].rgba.r * d[2] + tex_samples[3].rgba.r * d[3]) >> 8;
+ state->tex_g = (tex_samples[0].rgba.g * d[0] + tex_samples[1].rgba.g * d[1] + tex_samples[2].rgba.g * d[2] + tex_samples[3].rgba.g * d[3]) >> 8;
+ state->tex_b = (tex_samples[0].rgba.b * d[0] + tex_samples[1].rgba.b * d[1] + tex_samples[2].rgba.b * d[2] + tex_samples[3].rgba.b * d[3]) >> 8;
+ state->tex_a = (tex_samples[0].rgba.a * d[0] + tex_samples[1].rgba.a * d[1] + tex_samples[2].rgba.a * d[2] + tex_samples[3].rgba.a * d[3]) >> 8;*/
+/* state->tex_r = tex_samples[0].r;
+ state->tex_g = tex_samples[0].g;
+ state->tex_b = tex_samples[0].b;
+ state->tex_a = tex_samples[0].a;*/
+ }
+ else
+ {
+ // rgba_t tex_samples;
+ // voodoo_texture_state_t texture_state;
+// int s = state->tex_s >> (18+state->lod);
+// int t = state->tex_t >> (18+state->lod);
+ // int s, t;
+
+// state->tex_s -= 1 << (17+state->lod);
+// state->tex_t -= 1 << (17+state->lod);
+
+ s = state->tex_s >> (4+tex_lod);
+ t = state->tex_t >> (4+tex_lod);
+
+ texture_state.s = s;
+ texture_state.t = t;
+ tex_read(state, &texture_state, tmu);
+
+/* state->tex_r = tex_samples[0].rgba.r;
+ state->tex_g = tex_samples[0].rgba.g;
+ state->tex_b = tex_samples[0].rgba.b;
+ state->tex_a = tex_samples[0].rgba.a;*/
+ }
+}
+
+static inline void voodoo_tmu_fetch(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int tmu, int x)
+{
+ if (params->textureMode[tmu] & 1)
+ {
+ int64_t _w = 0;
+
+ if (tmu)
+ {
+ if (state->tmu1_w)
+ _w = (int64_t)((1ULL << 48) / state->tmu1_w);
+ state->tex_s = (int32_t)(((((state->tmu1_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30);
+ state->tex_t = (int32_t)(((((state->tmu1_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30);
+ }
+ else
+ {
+ if (state->tmu0_w)
+ _w = (int64_t)((1ULL << 48) / state->tmu0_w);
+ state->tex_s = (int32_t)(((((state->tmu0_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30);
+ state->tex_t = (int32_t)(((((state->tmu0_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30);
+ }
+
+ state->lod = state->tmu[tmu].lod + (fastlog(_w) - (19 << 8));
+ }
+ else
+ {
+ if (tmu)
+ {
+ state->tex_s = (int32_t)(state->tmu1_s >> (14+14));
+ state->tex_t = (int32_t)(state->tmu1_t >> (14+14));
+ }
+ else
+ {
+ state->tex_s = (int32_t)(state->tmu0_s >> (14+14));
+ state->tex_t = (int32_t)(state->tmu0_t >> (14+14));
+ }
+ state->lod = state->tmu[tmu].lod;
+ }
+
+ if (state->lod < state->lod_min[tmu])
+ state->lod = state->lod_min[tmu];
+ else if (state->lod > state->lod_max[tmu])
+ state->lod = state->lod_max[tmu];
+ state->lod_frac[tmu] = state->lod & 0xff;
+ state->lod >>= 8;
+
+ voodoo_get_texture(voodoo, params, state, tmu, x);
+}
+
+
+/*Perform texture fetch and blending for both TMUs*/
+static inline void voodoo_tmu_fetch_and_blend(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int x)
+{
+ int r,g,b,a;
+ int c_reverse, a_reverse;
+// int c_reverse1, a_reverse1;
+ int factor_r = 0, factor_g = 0, factor_b = 0, factor_a = 0;
+
+ voodoo_tmu_fetch(voodoo, params, state, 1, x);
+
+ if ((params->textureMode[1] & TEXTUREMODE_TRILINEAR) && (state->lod & 1))
+ {
+ c_reverse = tc_reverse_blend;
+ a_reverse = tca_reverse_blend;
+ }
+ else
+ {
+ c_reverse = !tc_reverse_blend;
+ a_reverse = !tca_reverse_blend;
+ }
+/* c_reverse1 = c_reverse;
+ a_reverse1 = a_reverse;*/
+ if (tc_sub_clocal_1)
+ {
+ switch (tc_mselect_1)
+ {
+ case TC_MSELECT_ZERO:
+ factor_r = factor_g = factor_b = 0;
+ break;
+ case TC_MSELECT_CLOCAL:
+ factor_r = state->tex_r[1];
+ factor_g = state->tex_g[1];
+ factor_b = state->tex_b[1];
+ break;
+ case TC_MSELECT_AOTHER:
+ factor_r = factor_g = factor_b = 0;
+ break;
+ case TC_MSELECT_ALOCAL:
+ factor_r = factor_g = factor_b = state->tex_a[1];
+ break;
+ case TC_MSELECT_DETAIL:
+ factor_r = (params->detail_bias[1] - state->lod) << params->detail_scale[1];
+ if (factor_r > params->detail_max[1])
+ factor_r = params->detail_max[1];
+ factor_g = factor_b = factor_r;
+ break;
+ case TC_MSELECT_LOD_FRAC:
+ factor_r = factor_g = factor_b = state->lod_frac[1];
+ break;
+ }
+ if (!c_reverse)
+ {
+ r = (-state->tex_r[1] * (factor_r + 1)) >> 8;
+ g = (-state->tex_g[1] * (factor_g + 1)) >> 8;
+ b = (-state->tex_b[1] * (factor_b + 1)) >> 8;
+ }
+ else
+ {
+ r = (-state->tex_r[1] * ((factor_r^0xff) + 1)) >> 8;
+ g = (-state->tex_g[1] * ((factor_g^0xff) + 1)) >> 8;
+ b = (-state->tex_b[1] * ((factor_b^0xff) + 1)) >> 8;
+ }
+ if (tc_add_clocal_1)
+ {
+ r += state->tex_r[1];
+ g += state->tex_g[1];
+ b += state->tex_b[1];
+ }
+ else if (tc_add_alocal_1)
+ {
+ r += state->tex_a[1];
+ g += state->tex_a[1];
+ b += state->tex_a[1];
+ }
+ state->tex_r[1] = CLAMP(r);
+ state->tex_g[1] = CLAMP(g);
+ state->tex_b[1] = CLAMP(b);
+ }
+ if (tca_sub_clocal_1)
+ {
+ switch (tca_mselect_1)
+ {
+ case TCA_MSELECT_ZERO:
+ factor_a = 0;
+ break;
+ case TCA_MSELECT_CLOCAL:
+ factor_a = state->tex_a[1];
+ break;
+ case TCA_MSELECT_AOTHER:
+ factor_a = 0;
+ break;
+ case TCA_MSELECT_ALOCAL:
+ factor_a = state->tex_a[1];
+ break;
+ case TCA_MSELECT_DETAIL:
+ factor_a = (params->detail_bias[1] - state->lod) << params->detail_scale[1];
+ if (factor_a > params->detail_max[1])
+ factor_a = params->detail_max[1];
+ break;
+ case TCA_MSELECT_LOD_FRAC:
+ factor_a = state->lod_frac[1];
+ break;
+ }
+ if (!a_reverse)
+ a = (-state->tex_a[1] * ((factor_a ^ 0xff) + 1)) >> 8;
+ else
+ a = (-state->tex_a[1] * (factor_a + 1)) >> 8;
+ if (tca_add_clocal_1 || tca_add_alocal_1)
+ a += state->tex_a[1];
+ state->tex_a[1] = CLAMP(a);
+ }
+
+
+ voodoo_tmu_fetch(voodoo, params, state, 0, x);
+
+ if ((params->textureMode[0] & TEXTUREMODE_TRILINEAR) && (state->lod & 1))
+ {
+ c_reverse = tc_reverse_blend;
+ a_reverse = tca_reverse_blend;
+ }
+ else
+ {
+ c_reverse = !tc_reverse_blend;
+ a_reverse = !tca_reverse_blend;
+ }
+
+ if (!tc_zero_other)
+ {
+ r = state->tex_r[1];
+ g = state->tex_g[1];
+ b = state->tex_b[1];
+ }
+ else
+ r = g = b = 0;
+ if (tc_sub_clocal)
+ {
+ r -= state->tex_r[0];
+ g -= state->tex_g[0];
+ b -= state->tex_b[0];
+ }
+ switch (tc_mselect)
+ {
+ case TC_MSELECT_ZERO:
+ factor_r = factor_g = factor_b = 0;
+ break;
+ case TC_MSELECT_CLOCAL:
+ factor_r = state->tex_r[0];
+ factor_g = state->tex_g[0];
+ factor_b = state->tex_b[0];
+ break;
+ case TC_MSELECT_AOTHER:
+ factor_r = factor_g = factor_b = state->tex_a[1];
+ break;
+ case TC_MSELECT_ALOCAL:
+ factor_r = factor_g = factor_b = state->tex_a[0];
+ break;
+ case TC_MSELECT_DETAIL:
+ factor_r = (params->detail_bias[0] - state->lod) << params->detail_scale[0];
+ if (factor_r > params->detail_max[0])
+ factor_r = params->detail_max[0];
+ factor_g = factor_b = factor_r;
+ break;
+ case TC_MSELECT_LOD_FRAC:
+ factor_r = factor_g = factor_b = state->lod_frac[0];
+ break;
+ }
+ if (!c_reverse)
+ {
+ r = (r * (factor_r + 1)) >> 8;
+ g = (g * (factor_g + 1)) >> 8;
+ b = (b * (factor_b + 1)) >> 8;
+ }
+ else
+ {
+ r = (r * ((factor_r^0xff) + 1)) >> 8;
+ g = (g * ((factor_g^0xff) + 1)) >> 8;
+ b = (b * ((factor_b^0xff) + 1)) >> 8;
+ }
+ if (tc_add_clocal)
+ {
+ r += state->tex_r[0];
+ g += state->tex_g[0];
+ b += state->tex_b[0];
+ }
+ else if (tc_add_alocal)
+ {
+ r += state->tex_a[0];
+ g += state->tex_a[0];
+ b += state->tex_a[0];
+ }
+
+ if (!tca_zero_other)
+ a = state->tex_a[1];
+ else
+ a = 0;
+ if (tca_sub_clocal)
+ a -= state->tex_a[0];
+ switch (tca_mselect)
+ {
+ case TCA_MSELECT_ZERO:
+ factor_a = 0;
+ break;
+ case TCA_MSELECT_CLOCAL:
+ factor_a = state->tex_a[0];
+ break;
+ case TCA_MSELECT_AOTHER:
+ factor_a = state->tex_a[1];
+ break;
+ case TCA_MSELECT_ALOCAL:
+ factor_a = state->tex_a[0];
+ break;
+ case TCA_MSELECT_DETAIL:
+ factor_a = (params->detail_bias[0] - state->lod) << params->detail_scale[0];
+ if (factor_a > params->detail_max[0])
+ factor_a = params->detail_max[0];
+ break;
+ case TCA_MSELECT_LOD_FRAC:
+ factor_a = state->lod_frac[0];
+ break;
+ }
+ if (a_reverse)
+ a = (a * ((factor_a ^ 0xff) + 1)) >> 8;
+ else
+ a = (a * (factor_a + 1)) >> 8;
+ if (tca_add_clocal || tca_add_alocal)
+ a += state->tex_a[0];
+
+
+ state->tex_r[0] = CLAMP(r);
+ state->tex_g[0] = CLAMP(g);
+ state->tex_b[0] = CLAMP(b);
+ state->tex_a[0] = CLAMP(a);
+
+ if (tc_invert_output)
+ {
+ state->tex_r[0] ^= 0xff;
+ state->tex_g[0] ^= 0xff;
+ state->tex_b[0] ^= 0xff;
+ }
+ if (tca_invert_output)
+ state->tex_a[0] ^= 0xff;
+}
+
+#if (defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32) && !(defined __amd64__)
+#include "vid_voodoo_codegen_x86.h"
+#elif (defined __amd64__)
+#include "vid_voodoo_codegen_x86-64.h"
+#else
+int voodoo_recomp = 0;
+#endif
+
+static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int ystart, int yend, int odd_even)
+{
+/* int rgb_sel = params->fbzColorPath & 3;
+ int a_sel = (params->fbzColorPath >> 2) & 3;
+ int cc_localselect = params->fbzColorPath & (1 << 4);
+ int cca_localselect = (params->fbzColorPath >> 5) & 3;
+ int cc_localselect_override = params->fbzColorPath & (1 << 7);
+ int cc_zero_other = params->fbzColorPath & (1 << 8);
+ int cc_sub_clocal = params->fbzColorPath & (1 << 9);
+ int cc_mselect = (params->fbzColorPath >> 10) & 7;
+ int cc_reverse_blend = params->fbzColorPath & (1 << 13);
+ int cc_add = (params->fbzColorPath >> 14) & 3;
+ int cc_add_alocal = params->fbzColorPath & (1 << 15);
+ int cc_invert_output = params->fbzColorPath & (1 << 16);
+ int cca_zero_other = params->fbzColorPath & (1 << 17);
+ int cca_sub_clocal = params->fbzColorPath & (1 << 18);
+ int cca_mselect = (params->fbzColorPath >> 19) & 7;
+ int cca_reverse_blend = params->fbzColorPath & (1 << 22);
+ int cca_add = (params->fbzColorPath >> 23) & 3;
+ int cca_invert_output = params->fbzColorPath & (1 << 25);
+ int src_afunc = (params->alphaMode >> 8) & 0xf;
+ int dest_afunc = (params->alphaMode >> 12) & 0xf;
+ int alpha_func = (params->alphaMode >> 1) & 7;
+ int a_ref = params->alphaMode >> 24;
+ int depth_op = (params->fbzMode >> 5) & 7;
+ int dither = params->fbzMode & FBZ_DITHER;*/
+ int texels;
+ int c;
+#ifndef NO_CODEGEN
+ uint8_t (*voodoo_draw)(voodoo_state_t *state, voodoo_params_t *params, int x, int real_y);
+#endif
+ int y_diff = SLI_ENABLED ? 2 : 1;
+ int y_origin = (voodoo->type >= VOODOO_BANSHEE) ? voodoo->y_origin_swap : (voodoo->v_disp-1);
+
+ if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH ||
+ (params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL)
+ texels = 1;
+ else
+ texels = 2;
+
+ state->clamp_s[0] = params->textureMode[0] & TEXTUREMODE_TCLAMPS;
+ state->clamp_t[0] = params->textureMode[0] & TEXTUREMODE_TCLAMPT;
+ state->clamp_s[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPS;
+ state->clamp_t[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPT;
+// int last_x;
+// pclog("voodoo_triangle : bottom-half %X %X %X %X %X %i %i %i %i\n", xstart, xend, dx1, dx2, dx2 * 36, xdir, y, yend, ydir);
+
+ for (c = 0; c <= LOD_MAX; c++)
+ {
+ state->tex[0][c] = &voodoo->texture_cache[0][params->tex_entry[0]].data[texture_offset[c]];
+ state->tex[1][c] = &voodoo->texture_cache[1][params->tex_entry[1]].data[texture_offset[c]];
+ }
+
+ state->tformat = params->tformat[0];
+
+ state->tex_w_mask[0] = params->tex_w_mask[0];
+ state->tex_h_mask[0] = params->tex_h_mask[0];
+ state->tex_shift[0] = params->tex_shift[0];
+ state->tex_lod[0] = params->tex_lod[0];
+ state->tex_w_mask[1] = params->tex_w_mask[1];
+ state->tex_h_mask[1] = params->tex_h_mask[1];
+ state->tex_shift[1] = params->tex_shift[1];
+ state->tex_lod[1] = params->tex_lod[1];
+
+ if ((params->fbzMode & 1) && (ystart < params->clipLowY))
+ {
+ int dy = params->clipLowY - ystart;
+
+ state->base_r += params->dRdY*dy;
+ state->base_g += params->dGdY*dy;
+ state->base_b += params->dBdY*dy;
+ state->base_a += params->dAdY*dy;
+ state->base_z += params->dZdY*dy;
+ state->tmu[0].base_s += params->tmu[0].dSdY*dy;
+ state->tmu[0].base_t += params->tmu[0].dTdY*dy;
+ state->tmu[0].base_w += params->tmu[0].dWdY*dy;
+ state->tmu[1].base_s += params->tmu[1].dSdY*dy;
+ state->tmu[1].base_t += params->tmu[1].dTdY*dy;
+ state->tmu[1].base_w += params->tmu[1].dWdY*dy;
+ state->base_w += params->dWdY*dy;
+ state->xstart += state->dx1*dy;
+ state->xend += state->dx2*dy;
+
+ ystart = params->clipLowY;
+ }
+
+ if ((params->fbzMode & 1) && (yend >= params->clipHighY))
+ yend = params->clipHighY;
+
+ state->y = ystart;
+// yend--;
+
+ if (SLI_ENABLED)
+ {
+ int test_y;
+
+ if (params->fbzMode & (1 << 17))
+ test_y = y_origin - state->y;
+ else
+ test_y = state->y;
+
+ if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (test_y & 1)) ||
+ ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(test_y & 1)))
+ {
+ state->y++;
+
+ state->base_r += params->dRdY;
+ state->base_g += params->dGdY;
+ state->base_b += params->dBdY;
+ state->base_a += params->dAdY;
+ state->base_z += params->dZdY;
+ state->tmu[0].base_s += params->tmu[0].dSdY;
+ state->tmu[0].base_t += params->tmu[0].dTdY;
+ state->tmu[0].base_w += params->tmu[0].dWdY;
+ state->tmu[1].base_s += params->tmu[1].dSdY;
+ state->tmu[1].base_t += params->tmu[1].dTdY;
+ state->tmu[1].base_w += params->tmu[1].dWdY;
+ state->base_w += params->dWdY;
+ state->xstart += state->dx1;
+ state->xend += state->dx2;
+ }
+ }
+#ifndef NO_CODEGEN
+ if (voodoo->use_recompiler)
+ voodoo_draw = voodoo_get_block(voodoo, params, state, odd_even);
+ else
+ voodoo_draw = NULL;
+#endif
+
+ if (voodoo_output)
+ pclog("dxAB=%08x dxBC=%08x dxAC=%08x\n", state->dxAB, state->dxBC, state->dxAC);
+// pclog("Start %i %i\n", ystart, voodoo->fbzMode & (1 << 17));
+
+ for (; state->y < yend; state->y += y_diff)
+ {
+ int x, x2;
+ int real_y = (state->y << 4) + 8;
+ int start_x, start_x2;
+ int dx;
+ uint16_t *fb_mem, *aux_mem;
+
+ state->ir = state->base_r;
+ state->ig = state->base_g;
+ state->ib = state->base_b;
+ state->ia = state->base_a;
+ state->z = state->base_z;
+ state->tmu0_s = state->tmu[0].base_s;
+ state->tmu0_t = state->tmu[0].base_t;
+ state->tmu0_w = state->tmu[0].base_w;
+ state->tmu1_s = state->tmu[1].base_s;
+ state->tmu1_t = state->tmu[1].base_t;
+ state->tmu1_w = state->tmu[1].base_w;
+ state->w = state->base_w;
+
+ x = (state->vertexAx << 12) + ((state->dxAC * (real_y - state->vertexAy)) >> 4);
+
+ if (real_y < state->vertexBy)
+ x2 = (state->vertexAx << 12) + ((state->dxAB * (real_y - state->vertexAy)) >> 4);
+ else
+ x2 = (state->vertexBx << 12) + ((state->dxBC * (real_y - state->vertexBy)) >> 4);
+
+ if (params->fbzMode & (1 << 17))
+ real_y = y_origin - (real_y >> 4);
+ else
+ real_y >>= 4;
+
+ if (SLI_ENABLED)
+ {
+ if (((real_y >> 1) & voodoo->odd_even_mask) != odd_even)
+ goto next_line;
+ }
+ else
+ {
+ if ((real_y & voodoo->odd_even_mask) != odd_even)
+ goto next_line;
+ }
+
+ start_x = x;
+
+ if (state->xdir > 0)
+ x2 -= (1 << 16);
+ else
+ x -= (1 << 16);
+ dx = ((x + 0x7000) >> 16) - (((state->vertexAx << 12) + 0x7000) >> 16);
+ start_x2 = x + 0x7000;
+ x = (x + 0x7000) >> 16;
+ x2 = (x2 + 0x7000) >> 16;
+
+ if (voodoo_output)
+ pclog("%03i:%03i : Ax=%08x start_x=%08x dSdX=%016llx dx=%08x s=%08x -> ", x, state->y, state->vertexAx << 8, start_x, params->tmu[0].dTdX, dx, state->tmu0_t);
+
+ state->ir += (params->dRdX * dx);
+ state->ig += (params->dGdX * dx);
+ state->ib += (params->dBdX * dx);
+ state->ia += (params->dAdX * dx);
+ state->z += (params->dZdX * dx);
+ state->tmu0_s += (params->tmu[0].dSdX * dx);
+ state->tmu0_t += (params->tmu[0].dTdX * dx);
+ state->tmu0_w += (params->tmu[0].dWdX * dx);
+ state->tmu1_s += (params->tmu[1].dSdX * dx);
+ state->tmu1_t += (params->tmu[1].dTdX * dx);
+ state->tmu1_w += (params->tmu[1].dWdX * dx);
+ state->w += (params->dWdX * dx);
+
+ if (voodoo_output)
+ pclog("%08llx %lli %lli\n", state->tmu0_t, state->tmu0_t >> (18+state->lod), (state->tmu0_t + (1 << (17+state->lod))) >> (18+state->lod));
+
+ if (params->fbzMode & 1)
+ {
+ if (state->xdir > 0)
+ {
+ if (x < params->clipLeft)
+ {
+ int dx = params->clipLeft - x;
+
+ state->ir += params->dRdX*dx;
+ state->ig += params->dGdX*dx;
+ state->ib += params->dBdX*dx;
+ state->ia += params->dAdX*dx;
+ state->z += params->dZdX*dx;
+ state->tmu0_s += params->tmu[0].dSdX*dx;
+ state->tmu0_t += params->tmu[0].dTdX*dx;
+ state->tmu0_w += params->tmu[0].dWdX*dx;
+ state->tmu1_s += params->tmu[1].dSdX*dx;
+ state->tmu1_t += params->tmu[1].dTdX*dx;
+ state->tmu1_w += params->tmu[1].dWdX*dx;
+ state->w += params->dWdX*dx;
+
+ x = params->clipLeft;
+ }
+ if (x2 >= params->clipRight)
+ x2 = params->clipRight-1;
+ }
+ else
+ {
+ if (x >= params->clipRight)
+ {
+ int dx = (params->clipRight-1) - x;
+
+ state->ir += params->dRdX*dx;
+ state->ig += params->dGdX*dx;
+ state->ib += params->dBdX*dx;
+ state->ia += params->dAdX*dx;
+ state->z += params->dZdX*dx;
+ state->tmu0_s += params->tmu[0].dSdX*dx;
+ state->tmu0_t += params->tmu[0].dTdX*dx;
+ state->tmu0_w += params->tmu[0].dWdX*dx;
+ state->tmu1_s += params->tmu[1].dSdX*dx;
+ state->tmu1_t += params->tmu[1].dTdX*dx;
+ state->tmu1_w += params->tmu[1].dWdX*dx;
+ state->w += params->dWdX*dx;
+
+ x = params->clipRight-1;
+ }
+ if (x2 < params->clipLeft)
+ x2 = params->clipLeft;
+ }
+ }
+
+ if (x2 < x && state->xdir > 0)
+ goto next_line;
+ if (x2 > x && state->xdir < 0)
+ goto next_line;
+
+ if (SLI_ENABLED)
+ {
+ state->fb_mem = fb_mem = (uint16_t *)&voodoo->fb_mem[params->draw_offset + ((real_y >> 1) * params->row_width)];
+ state->aux_mem = aux_mem = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + ((real_y >> 1) * params->row_width)) & voodoo->fb_mask];
+ }
+ else
+ {
+ if (params->col_tiled)
+ state->fb_mem = fb_mem = (uint16_t *)&voodoo->fb_mem[params->draw_offset + (real_y >> 5) * params->row_width + (real_y & 31) * 128];
+ else
+ state->fb_mem = fb_mem = (uint16_t *)&voodoo->fb_mem[params->draw_offset + (real_y * params->row_width)];
+ if (params->aux_tiled)
+ state->aux_mem = aux_mem = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (real_y >> 5) * params->aux_row_width + (real_y & 31) * 128) & voodoo->fb_mask];
+ else
+ state->aux_mem = aux_mem = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (real_y * params->row_width)) & voodoo->fb_mask];
+ }
+
+ if (voodoo_output)
+ pclog("%03i: x=%08x x2=%08x xstart=%08x xend=%08x dx=%08x start_x2=%08x\n", state->y, x, x2, state->xstart, state->xend, dx, start_x2);
+
+ state->pixel_count = 0;
+ state->texel_count = 0;
+ state->x = x;
+ state->x2 = x2;
+#ifndef NO_CODEGEN
+ if (voodoo->use_recompiler)
+ {
+ voodoo_draw(state, params, x, real_y);
+ }
+ else
+#endif
+ do
+ {
+ int x_tiled = (x & 63) | ((x >> 6) * 128*32/2);
+ start_x = x;
+ state->x = x;
+ voodoo->pixel_count[odd_even]++;
+ voodoo->texel_count[odd_even] += texels;
+ voodoo->fbiPixelsIn++;
+
+ if (voodoo_output)
+ pclog(" X=%03i T=%08x\n", x, state->tmu0_t);
+// if (voodoo->fbzMode & FBZ_RGB_WMASK)
+ {
+ int update = 1;
+ uint8_t cother_r, cother_g, cother_b, aother;
+ uint8_t clocal_r, clocal_g, clocal_b, alocal;
+ int src_r = 0, src_g = 0, src_b = 0, src_a = 0;
+ int msel_r, msel_g, msel_b, msel_a;
+ uint8_t dest_r, dest_g, dest_b, dest_a;
+ uint16_t dat;
+ int sel;
+ int32_t new_depth, w_depth;
+
+ if (state->w & 0xffff00000000)
+ w_depth = 0;
+ else if (!(state->w & 0xffff0000))
+ w_depth = 0xf001;
+ else
+ {
+ int exp = voodoo_fls((uint16_t)((uint32_t)state->w >> 16));
+ int mant = ((~(uint32_t)state->w >> (19 - exp))) & 0xfff;
+ w_depth = (exp << 12) + mant + 1;
+ if (w_depth > 0xffff)
+ w_depth = 0xffff;
+ }
+
+// w_depth = CLAMP16(w_depth);
+
+ if (params->fbzMode & FBZ_W_BUFFER)
+ new_depth = w_depth;
+ else
+ new_depth = CLAMP16(state->z >> 12);
+
+ if (params->fbzMode & FBZ_DEPTH_BIAS)
+ new_depth = CLAMP16(new_depth + (int16_t)params->zaColor);
+
+ if (params->fbzMode & FBZ_DEPTH_ENABLE)
+ {
+ uint16_t old_depth = voodoo->params.aux_tiled ? aux_mem[x_tiled] : aux_mem[x];
+
+ DEPTH_TEST((params->fbzMode & FBZ_DEPTH_SOURCE) ? (params->zaColor & 0xffff) : new_depth);
+ }
+
+ dat = voodoo->params.col_tiled ? fb_mem[x_tiled] : fb_mem[x];
+ dest_r = (dat >> 8) & 0xf8;
+ dest_g = (dat >> 3) & 0xfc;
+ dest_b = (dat << 3) & 0xf8;
+ dest_r |= (dest_r >> 5);
+ dest_g |= (dest_g >> 6);
+ dest_b |= (dest_b >> 5);
+ dest_a = 0xff;
+
+ if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED)
+ {
+ if ((params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL || !voodoo->dual_tmus)
+ {
+ /*TMU0 only sampling local colour or only one TMU, only sample TMU0*/
+ voodoo_tmu_fetch(voodoo, params, state, 0, x);
+ }
+ else if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH)
+ {
+ /*TMU0 in pass-through mode, only sample TMU1*/
+ voodoo_tmu_fetch(voodoo, params, state, 1, x);
+
+ state->tex_r[0] = state->tex_r[1];
+ state->tex_g[0] = state->tex_g[1];
+ state->tex_b[0] = state->tex_b[1];
+ state->tex_a[0] = state->tex_a[1];
+ }
+ else
+ {
+ voodoo_tmu_fetch_and_blend(voodoo, params, state, x);
+ }
+
+ if ((params->fbzMode & FBZ_CHROMAKEY) &&
+ state->tex_r[0] == params->chromaKey_r &&
+ state->tex_g[0] == params->chromaKey_g &&
+ state->tex_b[0] == params->chromaKey_b)
+ {
+ voodoo->fbiChromaFail++;
+ goto skip_pixel;
+ }
+ }
+
+ if (voodoo->trexInit1[0] & (1 << 18))
+ {
+ state->tex_r[0] = state->tex_g[0] = 0;
+ state->tex_b[0] = voodoo->tmuConfig;
+ }
+
+ if (cc_localselect_override)
+ sel = (state->tex_a[0] & 0x80) ? 1 : 0;
+ else
+ sel = cc_localselect;
+
+ if (sel)
+ {
+ clocal_r = (params->color0 >> 16) & 0xff;
+ clocal_g = (params->color0 >> 8) & 0xff;
+ clocal_b = params->color0 & 0xff;
+ }
+ else
+ {
+ clocal_r = CLAMP(state->ir >> 12);
+ clocal_g = CLAMP(state->ig >> 12);
+ clocal_b = CLAMP(state->ib >> 12);
+ }
+
+ switch (_rgb_sel)
+ {
+ case CC_LOCALSELECT_ITER_RGB: /*Iterated RGB*/
+ cother_r = CLAMP(state->ir >> 12);
+ cother_g = CLAMP(state->ig >> 12);
+ cother_b = CLAMP(state->ib >> 12);
+ break;
+
+ case CC_LOCALSELECT_TEX: /*TREX Color Output*/
+ cother_r = state->tex_r[0];
+ cother_g = state->tex_g[0];
+ cother_b = state->tex_b[0];
+ break;
+
+ case CC_LOCALSELECT_COLOR1: /*Color1 RGB*/
+ cother_r = (params->color1 >> 16) & 0xff;
+ cother_g = (params->color1 >> 8) & 0xff;
+ cother_b = params->color1 & 0xff;
+ break;
+
+ case CC_LOCALSELECT_LFB: /*Linear Frame Buffer*/
+ cother_r = src_r;
+ cother_g = src_g;
+ cother_b = src_b;
+ break;
+ }
+
+ switch (cca_localselect)
+ {
+ case CCA_LOCALSELECT_ITER_A:
+ alocal = CLAMP(state->ia >> 12);
+ break;
+
+ case CCA_LOCALSELECT_COLOR0:
+ alocal = (params->color0 >> 24) & 0xff;
+ break;
+
+ case CCA_LOCALSELECT_ITER_Z:
+ alocal = CLAMP(state->z >> 20);
+ break;
+
+ default:
+ fatal("Bad cca_localselect %i\n", cca_localselect);
+ alocal = 0xff;
+ break;
+ }
+
+ switch (a_sel)
+ {
+ case A_SEL_ITER_A:
+ aother = CLAMP(state->ia >> 12);
+ break;
+ case A_SEL_TEX:
+ aother = state->tex_a[0];
+ break;
+ case A_SEL_COLOR1:
+ aother = (params->color1 >> 24) & 0xff;
+ break;
+ default:
+ fatal("Bad a_sel %i\n", a_sel);
+ aother = 0;
+ break;
+ }
+
+ if (cc_zero_other)
+ {
+ src_r = 0;
+ src_g = 0;
+ src_b = 0;
+ }
+ else
+ {
+ src_r = cother_r;
+ src_g = cother_g;
+ src_b = cother_b;
+ }
+
+ if (cca_zero_other)
+ src_a = 0;
+ else
+ src_a = aother;
+
+ if (cc_sub_clocal)
+ {
+ src_r -= clocal_r;
+ src_g -= clocal_g;
+ src_b -= clocal_b;
+ }
+
+ if (cca_sub_clocal)
+ src_a -= alocal;
+
+ switch (cc_mselect)
+ {
+ case CC_MSELECT_ZERO:
+ msel_r = 0;
+ msel_g = 0;
+ msel_b = 0;
+ break;
+ case CC_MSELECT_CLOCAL:
+ msel_r = clocal_r;
+ msel_g = clocal_g;
+ msel_b = clocal_b;
+ break;
+ case CC_MSELECT_AOTHER:
+ msel_r = aother;
+ msel_g = aother;
+ msel_b = aother;
+ break;
+ case CC_MSELECT_ALOCAL:
+ msel_r = alocal;
+ msel_g = alocal;
+ msel_b = alocal;
+ break;
+ case CC_MSELECT_TEX:
+ msel_r = state->tex_a[0];
+ msel_g = state->tex_a[0];
+ msel_b = state->tex_a[0];
+ break;
+ case CC_MSELECT_TEXRGB:
+ msel_r = state->tex_r[0];
+ msel_g = state->tex_g[0];
+ msel_b = state->tex_b[0];
+ break;
+
+ default:
+ fatal("Bad cc_mselect %i\n", cc_mselect);
+ msel_r = 0;
+ msel_g = 0;
+ msel_b = 0;
+ break;
+ }
+
+ switch (cca_mselect)
+ {
+ case CCA_MSELECT_ZERO:
+ msel_a = 0;
+ break;
+ case CCA_MSELECT_ALOCAL:
+ msel_a = alocal;
+ break;
+ case CCA_MSELECT_AOTHER:
+ msel_a = aother;
+ break;
+ case CCA_MSELECT_ALOCAL2:
+ msel_a = alocal;
+ break;
+ case CCA_MSELECT_TEX:
+ msel_a = state->tex_a[0];
+ break;
+
+ default:
+ fatal("Bad cca_mselect %i\n", cca_mselect);
+ msel_a = 0;
+ break;
+ }
+
+ if (!cc_reverse_blend)
+ {
+ msel_r ^= 0xff;
+ msel_g ^= 0xff;
+ msel_b ^= 0xff;
+ }
+ msel_r++;
+ msel_g++;
+ msel_b++;
+
+ if (!cca_reverse_blend)
+ msel_a ^= 0xff;
+ msel_a++;
+
+ src_r = (src_r * msel_r) >> 8;
+ src_g = (src_g * msel_g) >> 8;
+ src_b = (src_b * msel_b) >> 8;
+ src_a = (src_a * msel_a) >> 8;
+
+ switch (cc_add)
+ {
+ case CC_ADD_CLOCAL:
+ src_r += clocal_r;
+ src_g += clocal_g;
+ src_b += clocal_b;
+ break;
+ case CC_ADD_ALOCAL:
+ src_r += alocal;
+ src_g += alocal;
+ src_b += alocal;
+ break;
+ case 0:
+ break;
+ default:
+ fatal("Bad cc_add %i\n", cc_add);
+ }
+
+ if (cca_add)
+ src_a += alocal;
+
+ src_r = CLAMP(src_r);
+ src_g = CLAMP(src_g);
+ src_b = CLAMP(src_b);
+ src_a = CLAMP(src_a);
+
+ if (cc_invert_output)
+ {
+ src_r ^= 0xff;
+ src_g ^= 0xff;
+ src_b ^= 0xff;
+ }
+ if (cca_invert_output)
+ src_a ^= 0xff;
+
+ if (params->fogMode & FOG_ENABLE)
+ APPLY_FOG(src_r, src_g, src_b, state->z, state->ia, state->w);
+
+ if (params->alphaMode & 1)
+ ALPHA_TEST(src_a);
+
+ if (params->alphaMode & (1 << 4))
+ {
+ if (dithersub && !dither2x2 && voodoo->dithersub_enabled)
+ {
+ dest_r = dithersub_rb[dest_r][real_y & 3][x & 3];
+ dest_g = dithersub_g [dest_g][real_y & 3][x & 3];
+ dest_b = dithersub_rb[dest_b][real_y & 3][x & 3];
+ }
+ if (dithersub && dither2x2 && voodoo->dithersub_enabled)
+ {
+ dest_r = dithersub_rb2x2[dest_r][real_y & 1][x & 1];
+ dest_g = dithersub_g2x2 [dest_g][real_y & 1][x & 1];
+ dest_b = dithersub_rb2x2[dest_b][real_y & 1][x & 1];
+ }
+ ALPHA_BLEND(src_r, src_g, src_b, src_a);
+ }
+
+ if (update)
+ {
+ if (dither)
+ {
+ if (dither2x2)
+ {
+ src_r = dither_rb2x2[src_r][real_y & 1][x & 1];
+ src_g = dither_g2x2[src_g][real_y & 1][x & 1];
+ src_b = dither_rb2x2[src_b][real_y & 1][x & 1];
+ }
+ else
+ {
+ src_r = dither_rb[src_r][real_y & 3][x & 3];
+ src_g = dither_g[src_g][real_y & 3][x & 3];
+ src_b = dither_rb[src_b][real_y & 3][x & 3];
+ }
+ }
+ else
+ {
+ src_r >>= 3;
+ src_g >>= 2;
+ src_b >>= 3;
+ }
+
+ if (params->fbzMode & FBZ_RGB_WMASK)
+ {
+ if (voodoo->params.col_tiled)
+ fb_mem[x_tiled] = src_b | (src_g << 5) | (src_r << 11);
+ else
+ fb_mem[x] = src_b | (src_g << 5) | (src_r << 11);
+ }
+ if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE))
+ {
+ if (voodoo->params.aux_tiled)
+ aux_mem[x_tiled] = new_depth;
+ else
+ aux_mem[x] = new_depth;
+ }
+ }
+ }
+ voodoo_output &= ~2;
+ voodoo->fbiPixelsOut++;
+skip_pixel:
+ if (state->xdir > 0)
+ {
+ state->ir += params->dRdX;
+ state->ig += params->dGdX;
+ state->ib += params->dBdX;
+ state->ia += params->dAdX;
+ state->z += params->dZdX;
+ state->tmu0_s += params->tmu[0].dSdX;
+ state->tmu0_t += params->tmu[0].dTdX;
+ state->tmu0_w += params->tmu[0].dWdX;
+ state->tmu1_s += params->tmu[1].dSdX;
+ state->tmu1_t += params->tmu[1].dTdX;
+ state->tmu1_w += params->tmu[1].dWdX;
+ state->w += params->dWdX;
+ }
+ else
+ {
+ state->ir -= params->dRdX;
+ state->ig -= params->dGdX;
+ state->ib -= params->dBdX;
+ state->ia -= params->dAdX;
+ state->z -= params->dZdX;
+ state->tmu0_s -= params->tmu[0].dSdX;
+ state->tmu0_t -= params->tmu[0].dTdX;
+ state->tmu0_w -= params->tmu[0].dWdX;
+ state->tmu1_s -= params->tmu[1].dSdX;
+ state->tmu1_t -= params->tmu[1].dTdX;
+ state->tmu1_w -= params->tmu[1].dWdX;
+ state->w -= params->dWdX;
+ }
+
+ x += state->xdir;
+ } while (start_x != x2);
+
+ voodoo->pixel_count[odd_even] += state->pixel_count;
+ voodoo->texel_count[odd_even] += state->texel_count;
+ voodoo->fbiPixelsIn += state->pixel_count;
+
+ if (voodoo->params.draw_offset == voodoo->params.front_offset && (real_y >> 1) < 2048)
+ voodoo->dirty_line[real_y >> 1] = 1;
+
+next_line:
+ if (SLI_ENABLED)
+ {
+ state->base_r += params->dRdY;
+ state->base_g += params->dGdY;
+ state->base_b += params->dBdY;
+ state->base_a += params->dAdY;
+ state->base_z += params->dZdY;
+ state->tmu[0].base_s += params->tmu[0].dSdY;
+ state->tmu[0].base_t += params->tmu[0].dTdY;
+ state->tmu[0].base_w += params->tmu[0].dWdY;
+ state->tmu[1].base_s += params->tmu[1].dSdY;
+ state->tmu[1].base_t += params->tmu[1].dTdY;
+ state->tmu[1].base_w += params->tmu[1].dWdY;
+ state->base_w += params->dWdY;
+ state->xstart += state->dx1;
+ state->xend += state->dx2;
+ }
+ state->base_r += params->dRdY;
+ state->base_g += params->dGdY;
+ state->base_b += params->dBdY;
+ state->base_a += params->dAdY;
+ state->base_z += params->dZdY;
+ state->tmu[0].base_s += params->tmu[0].dSdY;
+ state->tmu[0].base_t += params->tmu[0].dTdY;
+ state->tmu[0].base_w += params->tmu[0].dWdY;
+ state->tmu[1].base_s += params->tmu[1].dSdY;
+ state->tmu[1].base_t += params->tmu[1].dTdY;
+ state->tmu[1].base_w += params->tmu[1].dWdY;
+ state->base_w += params->dWdY;
+ state->xstart += state->dx1;
+ state->xend += state->dx2;
+ }
+
+ voodoo->texture_cache[0][params->tex_entry[0]].refcount_r[odd_even]++;
+ voodoo->texture_cache[1][params->tex_entry[1]].refcount_r[odd_even]++;
+}
+
+void voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params, int odd_even)
+{
+ voodoo_state_t state;
+ int vertexAy_adjusted;
+ int vertexCy_adjusted;
+ int dx, dy;
+
+ uint64_t tempdx, tempdy;
+ uint64_t tempLOD;
+ int LOD;
+ int lodbias;
+
+ voodoo->tri_count++;
+
+ dx = 8 - (params->vertexAx & 0xf);
+ if ((params->vertexAx & 0xf) > 8)
+ dx += 16;
+ dy = 8 - (params->vertexAy & 0xf);
+ if ((params->vertexAy & 0xf) > 8)
+ dy += 16;
+
+/* pclog("voodoo_triangle %i %i %i : vA %f, %f vB %f, %f vC %f, %f f %i,%i %08x %08x %08x,%08x tex=%i,%i fogMode=%08x\n", odd_even, voodoo->params_read_idx[odd_even], voodoo->params_read_idx[odd_even] & PARAM_MASK, (float)params->vertexAx / 16.0, (float)params->vertexAy / 16.0,
+ (float)params->vertexBx / 16.0, (float)params->vertexBy / 16.0,
+ (float)params->vertexCx / 16.0, (float)params->vertexCy / 16.0,
+ (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[0] : 0,
+ (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[1] : 0, params->fbzColorPath, params->alphaMode, params->textureMode[0],params->textureMode[1], params->tex_entry[0],params->tex_entry[1], params->fogMode);*/
+
+ state.base_r = params->startR;
+ state.base_g = params->startG;
+ state.base_b = params->startB;
+ state.base_a = params->startA;
+ state.base_z = params->startZ;
+ state.tmu[0].base_s = params->tmu[0].startS;
+ state.tmu[0].base_t = params->tmu[0].startT;
+ state.tmu[0].base_w = params->tmu[0].startW;
+ state.tmu[1].base_s = params->tmu[1].startS;
+ state.tmu[1].base_t = params->tmu[1].startT;
+ state.tmu[1].base_w = params->tmu[1].startW;
+ state.base_w = params->startW;
+
+ if (params->fbzColorPath & FBZ_PARAM_ADJUST)
+ {
+ state.base_r += (dx*params->dRdX + dy*params->dRdY) >> 4;
+ state.base_g += (dx*params->dGdX + dy*params->dGdY) >> 4;
+ state.base_b += (dx*params->dBdX + dy*params->dBdY) >> 4;
+ state.base_a += (dx*params->dAdX + dy*params->dAdY) >> 4;
+ state.base_z += (dx*params->dZdX + dy*params->dZdY) >> 4;
+ state.tmu[0].base_s += (dx*params->tmu[0].dSdX + dy*params->tmu[0].dSdY) >> 4;
+ state.tmu[0].base_t += (dx*params->tmu[0].dTdX + dy*params->tmu[0].dTdY) >> 4;
+ state.tmu[0].base_w += (dx*params->tmu[0].dWdX + dy*params->tmu[0].dWdY) >> 4;
+ state.tmu[1].base_s += (dx*params->tmu[1].dSdX + dy*params->tmu[1].dSdY) >> 4;
+ state.tmu[1].base_t += (dx*params->tmu[1].dTdX + dy*params->tmu[1].dTdY) >> 4;
+ state.tmu[1].base_w += (dx*params->tmu[1].dWdX + dy*params->tmu[1].dWdY) >> 4;
+ state.base_w += (dx*params->dWdX + dy*params->dWdY) >> 4;
+ }
+
+ tris++;
+
+ state.vertexAy = params->vertexAy & ~0xffff0000;
+ if (state.vertexAy & 0x8000)
+ state.vertexAy |= 0xffff0000;
+ state.vertexBy = params->vertexBy & ~0xffff0000;
+ if (state.vertexBy & 0x8000)
+ state.vertexBy |= 0xffff0000;
+ state.vertexCy = params->vertexCy & ~0xffff0000;
+ if (state.vertexCy & 0x8000)
+ state.vertexCy |= 0xffff0000;
+
+ state.vertexAx = params->vertexAx & ~0xffff0000;
+ if (state.vertexAx & 0x8000)
+ state.vertexAx |= 0xffff0000;
+ state.vertexBx = params->vertexBx & ~0xffff0000;
+ if (state.vertexBx & 0x8000)
+ state.vertexBx |= 0xffff0000;
+ state.vertexCx = params->vertexCx & ~0xffff0000;
+ if (state.vertexCx & 0x8000)
+ state.vertexCx |= 0xffff0000;
+
+ vertexAy_adjusted = (state.vertexAy+7) >> 4;
+ vertexCy_adjusted = (state.vertexCy+7) >> 4;
+
+ if (state.vertexBy - state.vertexAy)
+ state.dxAB = (int)((((int64_t)state.vertexBx << 12) - ((int64_t)state.vertexAx << 12)) << 4) / (int)(state.vertexBy - state.vertexAy);
+ else
+ state.dxAB = 0;
+ if (state.vertexCy - state.vertexAy)
+ state.dxAC = (int)((((int64_t)state.vertexCx << 12) - ((int64_t)state.vertexAx << 12)) << 4) / (int)(state.vertexCy - state.vertexAy);
+ else
+ state.dxAC = 0;
+ if (state.vertexCy - state.vertexBy)
+ state.dxBC = (int)((((int64_t)state.vertexCx << 12) - ((int64_t)state.vertexBx << 12)) << 4) / (int)(state.vertexCy - state.vertexBy);
+ else
+ state.dxBC = 0;
+
+ state.lod_min[0] = (params->tLOD[0] & 0x3f) << 6;
+ state.lod_max[0] = ((params->tLOD[0] >> 6) & 0x3f) << 6;
+ if (state.lod_max[0] > 0x800)
+ state.lod_max[0] = 0x800;
+ state.lod_min[1] = (params->tLOD[1] & 0x3f) << 6;
+ state.lod_max[1] = ((params->tLOD[1] >> 6) & 0x3f) << 6;
+ if (state.lod_max[1] > 0x800)
+ state.lod_max[1] = 0x800;
+
+ state.xstart = state.xend = state.vertexAx << 8;
+ state.xdir = params->sign ? -1 : 1;
+
+ state.y = (state.vertexAy + 8) >> 4;
+ state.ydir = 1;
+
+
+ tempdx = (params->tmu[0].dSdX >> 14) * (params->tmu[0].dSdX >> 14) + (params->tmu[0].dTdX >> 14) * (params->tmu[0].dTdX >> 14);
+ tempdy = (params->tmu[0].dSdY >> 14) * (params->tmu[0].dSdY >> 14) + (params->tmu[0].dTdY >> 14) * (params->tmu[0].dTdY >> 14);
+
+ if (tempdx > tempdy)
+ tempLOD = tempdx;
+ else
+ tempLOD = tempdy;
+
+ LOD = (int)(log2((double)tempLOD / (double)(1ULL << 36)) * 256);
+ LOD >>= 2;
+
+ lodbias = (params->tLOD[0] >> 12) & 0x3f;
+ if (lodbias & 0x20)
+ lodbias |= ~0x3f;
+ state.tmu[0].lod = LOD + (lodbias << 6);
+
+
+ tempdx = (params->tmu[1].dSdX >> 14) * (params->tmu[1].dSdX >> 14) + (params->tmu[1].dTdX >> 14) * (params->tmu[1].dTdX >> 14);
+ tempdy = (params->tmu[1].dSdY >> 14) * (params->tmu[1].dSdY >> 14) + (params->tmu[1].dTdY >> 14) * (params->tmu[1].dTdY >> 14);
+
+ if (tempdx > tempdy)
+ tempLOD = tempdx;
+ else
+ tempLOD = tempdy;
+
+ LOD = (int)(log2((double)tempLOD / (double)(1ULL << 36)) * 256);
+ LOD >>= 2;
+
+ lodbias = (params->tLOD[1] >> 12) & 0x3f;
+ if (lodbias & 0x20)
+ lodbias |= ~0x3f;
+ state.tmu[1].lod = LOD + (lodbias << 6);
+
+
+ voodoo_half_triangle(voodoo, params, &state, vertexAy_adjusted, vertexCy_adjusted, odd_even);
+}
+
+
+static void render_thread(void *param, int odd_even)
+{
+ voodoo_t *voodoo = (voodoo_t *)param;
+
+ while (1)
+ {
+ thread_set_event(voodoo->render_not_full_event[odd_even]);
+ thread_wait_event(voodoo->wake_render_thread[odd_even], -1);
+ thread_reset_event(voodoo->wake_render_thread[odd_even]);
+ voodoo->render_voodoo_busy[odd_even] = 1;
+
+ while (!PARAM_EMPTY(odd_even))
+ {
+ uint64_t start_time = timer_read();
+ uint64_t end_time;
+ voodoo_params_t *params = &voodoo->params_buffer[voodoo->params_read_idx[odd_even] & PARAM_MASK];
+
+ voodoo_triangle(voodoo, params, odd_even);
+
+ voodoo->params_read_idx[odd_even]++;
+
+ if (PARAM_ENTRIES(odd_even) > (PARAM_SIZE - 10))
+ thread_set_event(voodoo->render_not_full_event[odd_even]);
+
+ end_time = timer_read();
+ voodoo->render_time[odd_even] += end_time - start_time;
+ }
+
+ voodoo->render_voodoo_busy[odd_even] = 0;
+ }
+}
+
+void voodoo_render_thread_1(void *param)
+{
+ render_thread(param, 0);
+}
+void voodoo_render_thread_2(void *param)
+{
+ render_thread(param, 1);
+}
+void voodoo_render_thread_3(void *param)
+{
+ render_thread(param, 2);
+}
+void voodoo_render_thread_4(void *param)
+{
+ render_thread(param, 3);
+}
+
+void voodoo_queue_triangle(voodoo_t *voodoo, voodoo_params_t *params)
+{
+ voodoo_params_t *params_new = &voodoo->params_buffer[voodoo->params_write_idx & PARAM_MASK];
+
+ while (PARAM_FULL(0) || (voodoo->render_threads >= 2 && PARAM_FULL(1)) ||
+ (voodoo->render_threads == 4 && (PARAM_FULL(2) || PARAM_FULL(3))))
+ {
+ thread_reset_event(voodoo->render_not_full_event[0]);
+ if (voodoo->render_threads >= 2)
+ thread_reset_event(voodoo->render_not_full_event[1]);
+ if (voodoo->render_threads == 4)
+ {
+ thread_reset_event(voodoo->render_not_full_event[2]);
+ thread_reset_event(voodoo->render_not_full_event[3]);
+ }
+ if (PARAM_FULL(0))
+ thread_wait_event(voodoo->render_not_full_event[0], -1); /*Wait for room in ringbuffer*/
+ if (voodoo->render_threads >= 2 && PARAM_FULL(1))
+ thread_wait_event(voodoo->render_not_full_event[1], -1); /*Wait for room in ringbuffer*/
+ if (voodoo->render_threads == 4 && PARAM_FULL(2))
+ thread_wait_event(voodoo->render_not_full_event[2], -1); /*Wait for room in ringbuffer*/
+ if (voodoo->render_threads == 4 && PARAM_FULL(3))
+ thread_wait_event(voodoo->render_not_full_event[3], -1); /*Wait for room in ringbuffer*/
+ }
+
+ voodoo_use_texture(voodoo, params, 0);
+ if (voodoo->dual_tmus)
+ voodoo_use_texture(voodoo, params, 1);
+
+ memcpy(params_new, params, sizeof(voodoo_params_t));
+
+ voodoo->params_write_idx++;
+
+ if (PARAM_ENTRIES(0) < 4 || (voodoo->render_threads >= 2 && PARAM_ENTRIES(1) < 4) ||
+ (voodoo->render_threads == 4 && (PARAM_ENTRIES(2) < 4 || PARAM_ENTRIES(3) < 4)))
+ voodoo_wake_render_thread(voodoo);
+}
diff --git a/src/vid_voodoo_render.h b/src/vid_voodoo_render.h
new file mode 100644
index 0000000..9ba73dc
--- /dev/null
+++ b/src/vid_voodoo_render.h
@@ -0,0 +1,338 @@
+#if !(defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32) && !(defined __amd64__)
+#define NO_CODEGEN
+#endif
+
+#ifndef NO_CODEGEN
+void voodoo_codegen_init(voodoo_t *voodoo);
+void voodoo_codegen_close(voodoo_t *voodoo);
+#endif
+
+#define DEPTH_TEST(comp_depth) \
+ do \
+ { \
+ switch (depth_op) \
+ { \
+ case DEPTHOP_NEVER: \
+ voodoo->fbiZFuncFail++; \
+ goto skip_pixel; \
+ case DEPTHOP_LESSTHAN: \
+ if (!(comp_depth < old_depth)) \
+ { \
+ voodoo->fbiZFuncFail++; \
+ goto skip_pixel; \
+ } \
+ break; \
+ case DEPTHOP_EQUAL: \
+ if (!(comp_depth == old_depth)) \
+ { \
+ voodoo->fbiZFuncFail++; \
+ goto skip_pixel; \
+ } \
+ break; \
+ case DEPTHOP_LESSTHANEQUAL: \
+ if (!(comp_depth <= old_depth)) \
+ { \
+ voodoo->fbiZFuncFail++; \
+ goto skip_pixel; \
+ } \
+ break; \
+ case DEPTHOP_GREATERTHAN: \
+ if (!(comp_depth > old_depth)) \
+ { \
+ voodoo->fbiZFuncFail++; \
+ goto skip_pixel; \
+ } \
+ break; \
+ case DEPTHOP_NOTEQUAL: \
+ if (!(comp_depth != old_depth)) \
+ { \
+ voodoo->fbiZFuncFail++; \
+ goto skip_pixel; \
+ } \
+ break; \
+ case DEPTHOP_GREATERTHANEQUAL: \
+ if (!(comp_depth >= old_depth)) \
+ { \
+ voodoo->fbiZFuncFail++; \
+ goto skip_pixel; \
+ } \
+ break; \
+ case DEPTHOP_ALWAYS: \
+ break; \
+ } \
+ } while (0)
+
+#define APPLY_FOG(src_r, src_g, src_b, z, ia, w) \
+ do \
+ { \
+ if (params->fogMode & FOG_CONSTANT) \
+ { \
+ src_r += params->fogColor.r; \
+ src_g += params->fogColor.g; \
+ src_b += params->fogColor.b; \
+ } \
+ else \
+ { \
+ int fog_r, fog_g, fog_b, fog_a = 0; \
+ int fog_idx; \
+ \
+ if (!(params->fogMode & FOG_ADD)) \
+ { \
+ fog_r = params->fogColor.r; \
+ fog_g = params->fogColor.g; \
+ fog_b = params->fogColor.b; \
+ } \
+ else \
+ fog_r = fog_g = fog_b = 0; \
+ \
+ if (!(params->fogMode & FOG_MULT)) \
+ { \
+ fog_r -= src_r; \
+ fog_g -= src_g; \
+ fog_b -= src_b; \
+ } \
+ \
+ switch (params->fogMode & (FOG_Z|FOG_ALPHA)) \
+ { \
+ case 0: \
+ fog_idx = (w_depth >> 10) & 0x3f; \
+ \
+ fog_a = params->fogTable[fog_idx].fog; \
+ fog_a += (params->fogTable[fog_idx].dfog * ((w_depth >> 2) & 0xff)) >> 10; \
+ break; \
+ case FOG_Z: \
+ fog_a = (z >> 20) & 0xff; \
+ break; \
+ case FOG_ALPHA: \
+ fog_a = CLAMP(ia >> 12); \
+ break; \
+ case FOG_W: \
+ fog_a = CLAMP((w >> 32) & 0xff); \
+ break; \
+ } \
+ fog_a++; \
+ \
+ fog_r = (fog_r * fog_a) >> 8; \
+ fog_g = (fog_g * fog_a) >> 8; \
+ fog_b = (fog_b * fog_a) >> 8; \
+ \
+ if (params->fogMode & FOG_MULT) \
+ { \
+ src_r = fog_r; \
+ src_g = fog_g; \
+ src_b = fog_b; \
+ } \
+ else \
+ { \
+ src_r += fog_r; \
+ src_g += fog_g; \
+ src_b += fog_b; \
+ } \
+ } \
+ \
+ src_r = CLAMP(src_r); \
+ src_g = CLAMP(src_g); \
+ src_b = CLAMP(src_b); \
+ } while (0)
+
+#define ALPHA_TEST(src_a) \
+ do \
+ { \
+ switch (alpha_func) \
+ { \
+ case AFUNC_NEVER: \
+ voodoo->fbiAFuncFail++; \
+ goto skip_pixel; \
+ case AFUNC_LESSTHAN: \
+ if (!(src_a < a_ref)) \
+ { \
+ voodoo->fbiAFuncFail++; \
+ goto skip_pixel; \
+ } \
+ break; \
+ case AFUNC_EQUAL: \
+ if (!(src_a == a_ref)) \
+ { \
+ voodoo->fbiAFuncFail++; \
+ goto skip_pixel; \
+ } \
+ break; \
+ case AFUNC_LESSTHANEQUAL: \
+ if (!(src_a <= a_ref)) \
+ { \
+ voodoo->fbiAFuncFail++; \
+ goto skip_pixel; \
+ } \
+ break; \
+ case AFUNC_GREATERTHAN: \
+ if (!(src_a > a_ref)) \
+ { \
+ voodoo->fbiAFuncFail++; \
+ goto skip_pixel; \
+ } \
+ break; \
+ case AFUNC_NOTEQUAL: \
+ if (!(src_a != a_ref)) \
+ { \
+ voodoo->fbiAFuncFail++; \
+ goto skip_pixel; \
+ } \
+ break; \
+ case AFUNC_GREATERTHANEQUAL: \
+ if (!(src_a >= a_ref)) \
+ { \
+ voodoo->fbiAFuncFail++; \
+ goto skip_pixel; \
+ } \
+ break; \
+ case AFUNC_ALWAYS: \
+ break; \
+ } \
+ } while (0)
+
+#define ALPHA_BLEND(src_r, src_g, src_b, src_a) \
+ do \
+ { \
+ int _a; \
+ int newdest_r = 0, newdest_g = 0, newdest_b = 0; \
+ \
+ switch (dest_afunc) \
+ { \
+ case AFUNC_AZERO: \
+ newdest_r = newdest_g = newdest_b = 0; \
+ break; \
+ case AFUNC_ASRC_ALPHA: \
+ newdest_r = (dest_r * src_a) / 255; \
+ newdest_g = (dest_g * src_a) / 255; \
+ newdest_b = (dest_b * src_a) / 255; \
+ break; \
+ case AFUNC_A_COLOR: \
+ newdest_r = (dest_r * src_r) / 255; \
+ newdest_g = (dest_g * src_g) / 255; \
+ newdest_b = (dest_b * src_b) / 255; \
+ break; \
+ case AFUNC_ADST_ALPHA: \
+ newdest_r = (dest_r * dest_a) / 255; \
+ newdest_g = (dest_g * dest_a) / 255; \
+ newdest_b = (dest_b * dest_a) / 255; \
+ break; \
+ case AFUNC_AONE: \
+ newdest_r = dest_r; \
+ newdest_g = dest_g; \
+ newdest_b = dest_b; \
+ break; \
+ case AFUNC_AOMSRC_ALPHA: \
+ newdest_r = (dest_r * (255-src_a)) / 255; \
+ newdest_g = (dest_g * (255-src_a)) / 255; \
+ newdest_b = (dest_b * (255-src_a)) / 255; \
+ break; \
+ case AFUNC_AOM_COLOR: \
+ newdest_r = (dest_r * (255-src_r)) / 255; \
+ newdest_g = (dest_g * (255-src_g)) / 255; \
+ newdest_b = (dest_b * (255-src_b)) / 255; \
+ break; \
+ case AFUNC_AOMDST_ALPHA: \
+ newdest_r = (dest_r * (255-dest_a)) / 255; \
+ newdest_g = (dest_g * (255-dest_a)) / 255; \
+ newdest_b = (dest_b * (255-dest_a)) / 255; \
+ break; \
+ case AFUNC_ASATURATE: \
+ _a = MIN(src_a, 1-dest_a); \
+ newdest_r = (dest_r * _a) / 255; \
+ newdest_g = (dest_g * _a) / 255; \
+ newdest_b = (dest_b * _a) / 255; \
+ break; \
+ } \
+ \
+ switch (src_afunc) \
+ { \
+ case AFUNC_AZERO: \
+ src_r = src_g = src_b = 0; \
+ break; \
+ case AFUNC_ASRC_ALPHA: \
+ src_r = (src_r * src_a) / 255; \
+ src_g = (src_g * src_a) / 255; \
+ src_b = (src_b * src_a) / 255; \
+ break; \
+ case AFUNC_A_COLOR: \
+ src_r = (src_r * dest_r) / 255; \
+ src_g = (src_g * dest_g) / 255; \
+ src_b = (src_b * dest_b) / 255; \
+ break; \
+ case AFUNC_ADST_ALPHA: \
+ src_r = (src_r * dest_a) / 255; \
+ src_g = (src_g * dest_a) / 255; \
+ src_b = (src_b * dest_a) / 255; \
+ break; \
+ case AFUNC_AONE: \
+ break; \
+ case AFUNC_AOMSRC_ALPHA: \
+ src_r = (src_r * (255-src_a)) / 255; \
+ src_g = (src_g * (255-src_a)) / 255; \
+ src_b = (src_b * (255-src_a)) / 255; \
+ break; \
+ case AFUNC_AOM_COLOR: \
+ src_r = (src_r * (255-dest_r)) / 255; \
+ src_g = (src_g * (255-dest_g)) / 255; \
+ src_b = (src_b * (255-dest_b)) / 255; \
+ break; \
+ case AFUNC_AOMDST_ALPHA: \
+ src_r = (src_r * (255-dest_a)) / 255; \
+ src_g = (src_g * (255-dest_a)) / 255; \
+ src_b = (src_b * (255-dest_a)) / 255; \
+ break; \
+ case AFUNC_ACOLORBEFOREFOG: \
+ fatal("AFUNC_ACOLORBEFOREFOG\n"); \
+ break; \
+ } \
+ \
+ src_r += newdest_r; \
+ src_g += newdest_g; \
+ src_b += newdest_b; \
+ \
+ src_r = CLAMP(src_r); \
+ src_g = CLAMP(src_g); \
+ src_b = CLAMP(src_b); \
+ } while(0)
+
+
+
+void voodoo_render_thread_1(void *param);
+void voodoo_render_thread_2(void *param);
+void voodoo_render_thread_3(void *param);
+void voodoo_render_thread_4(void *param);
+void voodoo_queue_triangle(voodoo_t *voodoo, voodoo_params_t *params);
+
+extern int voodoo_recomp;
+extern int tris;
+
+static inline void voodoo_wake_render_thread(voodoo_t *voodoo)
+{
+ thread_set_event(voodoo->wake_render_thread[0]); /*Wake up render thread if moving from idle*/
+ if (voodoo->render_threads >= 2)
+ thread_set_event(voodoo->wake_render_thread[1]); /*Wake up render thread if moving from idle*/
+ if (voodoo->render_threads == 4)
+ {
+ thread_set_event(voodoo->wake_render_thread[2]); /*Wake up render thread if moving from idle*/
+ thread_set_event(voodoo->wake_render_thread[3]); /*Wake up render thread if moving from idle*/
+ }
+}
+
+static inline void voodoo_wait_for_render_thread_idle(voodoo_t *voodoo)
+{
+ while (!PARAM_EMPTY(0) || (voodoo->render_threads >= 2 && !PARAM_EMPTY(1)) ||
+ (voodoo->render_threads == 4 && (!PARAM_EMPTY(2) || !PARAM_EMPTY(3))) ||
+ voodoo->render_voodoo_busy[0] || (voodoo->render_threads >= 2 && voodoo->render_voodoo_busy[1]) ||
+ (voodoo->render_threads == 4 && (voodoo->render_voodoo_busy[2] || voodoo->render_voodoo_busy[3])))
+ {
+ voodoo_wake_render_thread(voodoo);
+ if (!PARAM_EMPTY(0) || voodoo->render_voodoo_busy[0])
+ thread_wait_event(voodoo->render_not_full_event[0], 1);
+ if (voodoo->render_threads >= 2 && (!PARAM_EMPTY(1) || voodoo->render_voodoo_busy[1]))
+ thread_wait_event(voodoo->render_not_full_event[1], 1);
+ if (voodoo->render_threads == 4 && (!PARAM_EMPTY(2) || voodoo->render_voodoo_busy[2]))
+ thread_wait_event(voodoo->render_not_full_event[2], 1);
+ if (voodoo->render_threads == 4 && (!PARAM_EMPTY(3) || voodoo->render_voodoo_busy[3]))
+ thread_wait_event(voodoo->render_not_full_event[3], 1);
+ }
+}
diff --git a/src/vid_voodoo_setup.c b/src/vid_voodoo_setup.c
new file mode 100644
index 0000000..360d14a
--- /dev/null
+++ b/src/vid_voodoo_setup.c
@@ -0,0 +1,216 @@
+#include "ibm.h"
+#include "device.h"
+#include "mem.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_svga.h"
+#include "vid_voodoo.h"
+#include "vid_voodoo_common.h"
+#include "vid_voodoo_regs.h"
+#include "vid_voodoo_render.h"
+#include "vid_voodoo_setup.h"
+
+void voodoo_triangle_setup(voodoo_t *voodoo)
+{
+ float dxAB, dxBC, dyAB, dyBC;
+ float area;
+ int va = 0, vb = 1, vc = 2;
+ vert_t verts[3];
+
+ verts[0] = voodoo->verts[0];
+ verts[1] = voodoo->verts[1];
+ verts[2] = voodoo->verts[2];
+
+ if (verts[0].sVy < verts[1].sVy)
+ {
+ if (verts[1].sVy < verts[2].sVy)
+ {
+ /* V1>V0, V2>V1, V2>V1>V0*/
+ va = 0; /*OK*/
+ vb = 1;
+ vc = 2;
+ }
+ else
+ {
+ /* V1>V0, V1>V2*/
+ if (verts[0].sVy < verts[2].sVy)
+ {
+ /* V1>V0, V1>V2, V2>V0, V1>V2>V0*/
+ va = 0;
+ vb = 2;
+ vc = 1;
+ }
+ else
+ {
+ /* V1>V0, V1>V2, V0>V2, V1>V0>V2*/
+ va = 2;
+ vb = 0;
+ vc = 1;
+ }
+ }
+ }
+ else
+ {
+ if (verts[1].sVy < verts[2].sVy)
+ {
+ /* V0>V1, V2>V1*/
+ if (verts[0].sVy < verts[2].sVy)
+ {
+ /* V0>V1, V2>V1, V2>V0, V2>V0>V1*/
+ va = 1;
+ vb = 0;
+ vc = 2;
+ }
+ else
+ {
+ /* V0>V1, V2>V1, V0>V2, V0>V2>V1*/
+ va = 1;
+ vb = 2;
+ vc = 0;
+ }
+ }
+ else
+ {
+ /*V0>V1>V2*/
+ va = 2;
+ vb = 1;
+ vc = 0;
+ }
+ }
+
+ dxAB = verts[0].sVx - verts[1].sVx;
+ dxBC = verts[1].sVx - verts[2].sVx;
+ dyAB = verts[0].sVy - verts[1].sVy;
+ dyBC = verts[1].sVy - verts[2].sVy;
+
+ area = dxAB * dyBC - dxBC * dyAB;
+
+ if (area == 0.0)
+ return;
+
+ if (voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE)
+ {
+ int cull_sign = voodoo->sSetupMode & SETUPMODE_CULLING_SIGN;
+ int sign = (area < 0.0);
+
+ if ((voodoo->sSetupMode & (SETUPMODE_CULLING_ENABLE | SETUPMODE_DISABLE_PINGPONG))
+ == SETUPMODE_CULLING_ENABLE && voodoo->cull_pingpong)
+ cull_sign = !cull_sign;
+
+ if (cull_sign && sign)
+ return;
+ if (!cull_sign && !sign)
+ return;
+ }
+
+
+ dxAB = verts[va].sVx - verts[vb].sVx;
+ dxBC = verts[vb].sVx - verts[vc].sVx;
+ dyAB = verts[va].sVy - verts[vb].sVy;
+ dyBC = verts[vb].sVy - verts[vc].sVy;
+
+ area = dxAB * dyBC - dxBC * dyAB;
+
+ dxAB /= area;
+ dxBC /= area;
+ dyAB /= area;
+ dyBC /= area;
+
+
+
+ voodoo->params.vertexAx = (int32_t)(int16_t)((int32_t)(verts[va].sVx * 16.0f) & 0xffff);
+ voodoo->params.vertexAy = (int32_t)(int16_t)((int32_t)(verts[va].sVy * 16.0f) & 0xffff);
+ voodoo->params.vertexBx = (int32_t)(int16_t)((int32_t)(verts[vb].sVx * 16.0f) & 0xffff);
+ voodoo->params.vertexBy = (int32_t)(int16_t)((int32_t)(verts[vb].sVy * 16.0f) & 0xffff);
+ voodoo->params.vertexCx = (int32_t)(int16_t)((int32_t)(verts[vc].sVx * 16.0f) & 0xffff);
+ voodoo->params.vertexCy = (int32_t)(int16_t)((int32_t)(verts[vc].sVy * 16.0f) & 0xffff);
+
+ if (voodoo->params.vertexAy > voodoo->params.vertexBy || voodoo->params.vertexBy > voodoo->params.vertexCy)
+ {
+ pclog("triangle_setup wrong order %d %d %d\n", voodoo->params.vertexAy, voodoo->params.vertexBy, voodoo->params.vertexCy);
+ return;
+ }
+
+ if (voodoo->sSetupMode & SETUPMODE_RGB)
+ {
+ voodoo->params.startR = (int32_t)(verts[va].sRed * 4096.0f);
+ voodoo->params.dRdX = (int32_t)(((verts[va].sRed - verts[vb].sRed) * dyBC - (verts[vb].sRed - verts[vc].sRed) * dyAB) * 4096.0f);
+ voodoo->params.dRdY = (int32_t)(((verts[vb].sRed - verts[vc].sRed) * dxAB - (verts[va].sRed - verts[vb].sRed) * dxBC) * 4096.0f);
+ voodoo->params.startG = (int32_t)(verts[va].sGreen * 4096.0f);
+ voodoo->params.dGdX = (int32_t)(((verts[va].sGreen - verts[vb].sGreen) * dyBC - (verts[vb].sGreen - verts[vc].sGreen) * dyAB) * 4096.0f);
+ voodoo->params.dGdY = (int32_t)(((verts[vb].sGreen - verts[vc].sGreen) * dxAB - (verts[va].sGreen - verts[vb].sGreen) * dxBC) * 4096.0f);
+ voodoo->params.startB = (int32_t)(verts[va].sBlue * 4096.0f);
+ voodoo->params.dBdX = (int32_t)(((verts[va].sBlue - verts[vb].sBlue) * dyBC - (verts[vb].sBlue - verts[vc].sBlue) * dyAB) * 4096.0f);
+ voodoo->params.dBdY = (int32_t)(((verts[vb].sBlue - verts[vc].sBlue) * dxAB - (verts[va].sBlue - verts[vb].sBlue) * dxBC) * 4096.0f);
+ }
+ if (voodoo->sSetupMode & SETUPMODE_ALPHA)
+ {
+ voodoo->params.startA = (int32_t)(verts[va].sAlpha * 4096.0f);
+ voodoo->params.dAdX = (int32_t)(((verts[va].sAlpha - verts[vb].sAlpha) * dyBC - (verts[vb].sAlpha - verts[vc].sAlpha) * dyAB) * 4096.0f);
+ voodoo->params.dAdY = (int32_t)(((verts[vb].sAlpha - verts[vc].sAlpha) * dxAB - (verts[va].sAlpha - verts[vb].sAlpha) * dxBC) * 4096.0f);
+ }
+ if (voodoo->sSetupMode & SETUPMODE_Z)
+ {
+ voodoo->params.startZ = (int32_t)(verts[va].sVz * 4096.0f);
+ voodoo->params.dZdX = (int32_t)(((verts[va].sVz - verts[vb].sVz) * dyBC - (verts[vb].sVz - verts[vc].sVz) * dyAB) * 4096.0f);
+ voodoo->params.dZdY = (int32_t)(((verts[vb].sVz - verts[vc].sVz) * dxAB - (verts[va].sVz - verts[vb].sVz) * dxBC) * 4096.0f);
+ }
+ if (voodoo->sSetupMode & SETUPMODE_Wb)
+ {
+ voodoo->params.startW = (int64_t)(verts[va].sWb * 4294967296.0f);
+ voodoo->params.dWdX = (int64_t)(((verts[va].sWb - verts[vb].sWb) * dyBC - (verts[vb].sWb - verts[vc].sWb) * dyAB) * 4294967296.0f);
+ voodoo->params.dWdY = (int64_t)(((verts[vb].sWb - verts[vc].sWb) * dxAB - (verts[va].sWb - verts[vb].sWb) * dxBC) * 4294967296.0f);
+ voodoo->params.tmu[0].startW = voodoo->params.tmu[1].startW = voodoo->params.startW;
+ voodoo->params.tmu[0].dWdX = voodoo->params.tmu[1].dWdX = voodoo->params.dWdX;
+ voodoo->params.tmu[0].dWdY = voodoo->params.tmu[1].dWdY = voodoo->params.dWdY;
+ }
+ if (voodoo->sSetupMode & SETUPMODE_W0)
+ {
+ voodoo->params.tmu[0].startW = (int64_t)(verts[va].sW0 * 4294967296.0f);
+ voodoo->params.tmu[0].dWdX = (int64_t)(((verts[va].sW0 - verts[vb].sW0) * dyBC - (verts[vb].sW0 - verts[vc].sW0) * dyAB) * 4294967296.0f);
+ voodoo->params.tmu[0].dWdY = (int64_t)(((verts[vb].sW0 - verts[vc].sW0) * dxAB - (verts[va].sW0 - verts[vb].sW0) * dxBC) * 4294967296.0f);
+ voodoo->params.tmu[1].startW = voodoo->params.tmu[0].startW;
+ voodoo->params.tmu[1].dWdX = voodoo->params.tmu[0].dWdX;
+ voodoo->params.tmu[1].dWdY = voodoo->params.tmu[0].dWdY;
+ }
+ if (voodoo->sSetupMode & SETUPMODE_S0_T0)
+ {
+ voodoo->params.tmu[0].startS = (int64_t)(verts[va].sS0 * 4294967296.0f);
+ voodoo->params.tmu[0].dSdX = (int64_t)(((verts[va].sS0 - verts[vb].sS0) * dyBC - (verts[vb].sS0 - verts[vc].sS0) * dyAB) * 4294967296.0f);
+ voodoo->params.tmu[0].dSdY = (int64_t)(((verts[vb].sS0 - verts[vc].sS0) * dxAB - (verts[va].sS0 - verts[vb].sS0) * dxBC) * 4294967296.0f);
+ voodoo->params.tmu[0].startT = (int64_t)(verts[va].sT0 * 4294967296.0f);
+ voodoo->params.tmu[0].dTdX = (int64_t)(((verts[va].sT0 - verts[vb].sT0) * dyBC - (verts[vb].sT0 - verts[vc].sT0) * dyAB) * 4294967296.0f);
+ voodoo->params.tmu[0].dTdY = (int64_t)(((verts[vb].sT0 - verts[vc].sT0) * dxAB - (verts[va].sT0 - verts[vb].sT0) * dxBC) * 4294967296.0f);
+ voodoo->params.tmu[1].startS = voodoo->params.tmu[0].startS;
+ voodoo->params.tmu[1].dSdX = voodoo->params.tmu[0].dSdX;
+ voodoo->params.tmu[1].dSdY = voodoo->params.tmu[0].dSdY;
+ voodoo->params.tmu[1].startT = voodoo->params.tmu[0].startT;
+ voodoo->params.tmu[1].dTdX = voodoo->params.tmu[0].dTdX;
+ voodoo->params.tmu[1].dTdY = voodoo->params.tmu[0].dTdY;
+ }
+ if (voodoo->sSetupMode & SETUPMODE_W1)
+ {
+ voodoo->params.tmu[1].startW = (int64_t)(verts[va].sW1 * 4294967296.0f);
+ voodoo->params.tmu[1].dWdX = (int64_t)(((verts[va].sW1 - verts[vb].sW1) * dyBC - (verts[vb].sW1 - verts[vc].sW1) * dyAB) * 4294967296.0f);
+ voodoo->params.tmu[1].dWdY = (int64_t)(((verts[vb].sW1 - verts[vc].sW1) * dxAB - (verts[va].sW1 - verts[vb].sW1) * dxBC) * 4294967296.0f);
+ }
+ if (voodoo->sSetupMode & SETUPMODE_S1_T1)
+ {
+ voodoo->params.tmu[1].startS = (int64_t)(verts[va].sS1 * 4294967296.0f);
+ voodoo->params.tmu[1].dSdX = (int64_t)(((verts[va].sS1 - verts[vb].sS1) * dyBC - (verts[vb].sS1 - verts[vc].sS1) * dyAB) * 4294967296.0f);
+ voodoo->params.tmu[1].dSdY = (int64_t)(((verts[vb].sS1 - verts[vc].sS1) * dxAB - (verts[va].sS1 - verts[vb].sS1) * dxBC) * 4294967296.0f);
+ voodoo->params.tmu[1].startT = (int64_t)(verts[va].sT1 * 4294967296.0f);
+ voodoo->params.tmu[1].dTdX = (int64_t)(((verts[va].sT1 - verts[vb].sT1) * dyBC - (verts[vb].sT1 - verts[vc].sT1) * dyAB) * 4294967296.0f);
+ voodoo->params.tmu[1].dTdY = (int64_t)(((verts[vb].sT1 - verts[vc].sT1) * dxAB - (verts[va].sT1 - verts[vb].sT1) * dxBC) * 4294967296.0f);
+ }
+
+ voodoo->params.sign = (area < 0.0);
+
+ if (voodoo->ncc_dirty[0])
+ voodoo_update_ncc(voodoo, 0);
+ if (voodoo->ncc_dirty[1])
+ voodoo_update_ncc(voodoo, 1);
+ voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0;
+
+ voodoo_queue_triangle(voodoo, &voodoo->params);
+}
diff --git a/src/vid_voodoo_setup.h b/src/vid_voodoo_setup.h
new file mode 100644
index 0000000..06d2f8d
--- /dev/null
+++ b/src/vid_voodoo_setup.h
@@ -0,0 +1 @@
+void voodoo_triangle_setup(voodoo_t *voodoo);
diff --git a/src/vid_voodoo_texture.c b/src/vid_voodoo_texture.c
new file mode 100644
index 0000000..f1d5c78
--- /dev/null
+++ b/src/vid_voodoo_texture.c
@@ -0,0 +1,583 @@
+#include
+#include
+#include "ibm.h"
+#include "device.h"
+#include "mem.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_svga.h"
+#include "vid_voodoo.h"
+#include "vid_voodoo_common.h"
+#include "vid_voodoo_dither.h"
+#include "vid_voodoo_regs.h"
+#include "vid_voodoo_render.h"
+#include "vid_voodoo_texture.h"
+
+void voodoo_recalc_tex(voodoo_t *voodoo, int tmu)
+{
+ int aspect = (voodoo->params.tLOD[tmu] >> 21) & 3;
+ int width = 256, height = 256;
+ int shift = 8;
+ int lod;
+ uint32_t base = voodoo->params.texBaseAddr[tmu];
+ uint32_t offset = 0;
+ int tex_lod = 0;
+ uint32_t offsets[LOD_MAX+3];
+ int widths[LOD_MAX+3], heights[LOD_MAX+3], shifts[LOD_MAX+3];
+
+ if (voodoo->params.tLOD[tmu] & LOD_S_IS_WIDER)
+ height >>= aspect;
+ else
+ {
+ width >>= aspect;
+ shift -= aspect;
+ }
+
+ for (lod = 0; lod <= LOD_MAX + 2; lod++)
+ {
+ offsets[lod] = offset;
+ widths[lod] = width >> lod;
+ heights[lod] = height >> lod;
+ shifts[lod] = shift - lod;
+
+ if (!widths[lod])
+ widths[lod] = 1;
+ if (!heights[lod])
+ heights[lod] = 1;
+ if (shifts[lod] < 0)
+ shifts[lod] = 0;
+
+ if (!(voodoo->params.tLOD[tmu] & LOD_SPLIT) ||
+ ((lod & 1) && (voodoo->params.tLOD[tmu] & LOD_ODD)) ||
+ (!(lod & 1) && !(voodoo->params.tLOD[tmu] & LOD_ODD)))
+ {
+ if (voodoo->params.tformat[tmu] & 8)
+ offset += (width >> lod) * (height >> lod) * 2;
+ else
+ offset += (width >> lod) * (height >> lod);
+ }
+ }
+
+
+ if ((voodoo->params.textureMode[tmu] & TEXTUREMODE_TRILINEAR) && (voodoo->params.tLOD[tmu] & LOD_ODD))
+ tex_lod++; /*Skip LOD 0*/
+
+// pclog("TMU %i: %08x\n", tmu, voodoo->params.textureMode[tmu]);
+ for (lod = 0; lod <= LOD_MAX+1; lod++)
+ {
+ if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)
+ {
+ switch (tex_lod)
+ {
+ case 0:
+ base = voodoo->params.texBaseAddr[tmu];
+ break;
+ case 1:
+ base = voodoo->params.texBaseAddr1[tmu];
+ break;
+ case 2:
+ base = voodoo->params.texBaseAddr2[tmu];
+ break;
+ default:
+ base = voodoo->params.texBaseAddr38[tmu];
+ break;
+ }
+ }
+
+ voodoo->params.tex_base[tmu][lod] = base + offsets[tex_lod];
+ if (voodoo->params.tformat[tmu] & 8)
+ voodoo->params.tex_end[tmu][lod] = base + offsets[tex_lod] + (widths[tex_lod] * heights[tex_lod] * 2);
+ else
+ voodoo->params.tex_end[tmu][lod] = base + offsets[tex_lod] + (widths[tex_lod] * heights[tex_lod]);
+ voodoo->params.tex_w_mask[tmu][lod] = widths[tex_lod] - 1;
+ voodoo->params.tex_w_nmask[tmu][lod] = ~(widths[tex_lod] - 1);
+ voodoo->params.tex_h_mask[tmu][lod] = heights[tex_lod] - 1;
+ voodoo->params.tex_shift[tmu][lod] = shifts[tex_lod];
+ voodoo->params.tex_lod[tmu][lod] = tex_lod;
+
+ if (!(voodoo->params.textureMode[tmu] & TEXTUREMODE_TRILINEAR) ||
+ ((lod & 1) && (voodoo->params.tLOD[tmu] & LOD_ODD)) ||
+ (!(lod & 1) && !(voodoo->params.tLOD[tmu] & LOD_ODD)))
+ {
+ if (!(voodoo->params.tLOD[tmu] & LOD_ODD) || lod != 0)
+ {
+ if (voodoo->params.textureMode[tmu] & TEXTUREMODE_TRILINEAR)
+ tex_lod += 2;
+ else
+ tex_lod++;
+ }
+ }
+ }
+
+ voodoo->params.tex_width[tmu] = width;
+}
+
+#define makergba(r, g, b, a) ((b) | ((g) << 8) | ((r) << 16) | ((a) << 24))
+
+void voodoo_use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu)
+{
+ int c, d;
+ int lod;
+ int lod_min, lod_max;
+ uint32_t addr = 0, addr_end;
+ uint32_t palette_checksum;
+
+ lod_min = (params->tLOD[tmu] >> 2) & 15;
+ lod_max = (params->tLOD[tmu] >> 8) & 15;
+
+ if (params->tformat[tmu] == TEX_PAL8 || params->tformat[tmu] == TEX_APAL8 || params->tformat[tmu] == TEX_APAL88)
+ {
+ if (voodoo->palette_dirty[tmu])
+ {
+ palette_checksum = 0;
+
+ for (c = 0; c < 256; c++)
+ palette_checksum ^= voodoo->palette[tmu][c].u;
+
+ voodoo->palette_checksum[tmu] = palette_checksum;
+ voodoo->palette_dirty[tmu] = 0;
+ }
+ else
+ palette_checksum = voodoo->palette_checksum[tmu];
+ }
+ else
+ palette_checksum = 0;
+
+ if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR))
+ addr = params->texBaseAddr1[tmu];
+ else
+ addr = params->texBaseAddr[tmu];
+
+ /*Try to find texture in cache*/
+ for (c = 0; c < TEX_CACHE_MAX; c++)
+ {
+ if (voodoo->texture_cache[tmu][c].base == addr &&
+ voodoo->texture_cache[tmu][c].tLOD == (params->tLOD[tmu] & 0xf00fff) &&
+ voodoo->texture_cache[tmu][c].palette_checksum == palette_checksum)
+ {
+ params->tex_entry[tmu] = c;
+ voodoo->texture_cache[tmu][c].refcount++;
+ return;
+ }
+ }
+
+ /*Texture not found, search for unused texture*/
+ do
+ {
+ for (c = 0; c < TEX_CACHE_MAX; c++)
+ {
+ voodoo->texture_last_removed++;
+ voodoo->texture_last_removed &= (TEX_CACHE_MAX-1);
+ if (voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount == voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount_r[0] &&
+ (voodoo->render_threads == 1 || voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount == voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount_r[1]))
+ break;
+ }
+ if (c == TEX_CACHE_MAX)
+ voodoo_wait_for_render_thread_idle(voodoo);
+ } while (c == TEX_CACHE_MAX);
+ if (c == TEX_CACHE_MAX)
+ fatal("Texture cache full!\n");
+
+ c = voodoo->texture_last_removed;
+
+
+ if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR))
+ voodoo->texture_cache[tmu][c].base = params->texBaseAddr1[tmu];
+ else
+ voodoo->texture_cache[tmu][c].base = params->texBaseAddr[tmu];
+ voodoo->texture_cache[tmu][c].tLOD = params->tLOD[tmu] & 0xf00fff;
+
+ lod_min = (params->tLOD[tmu] >> 2) & 15;
+ lod_max = (params->tLOD[tmu] >> 8) & 15;
+// pclog(" add new texture to %i tformat=%i %08x LOD=%i-%i tmu=%i\n", c, voodoo->params.tformat[tmu], params->texBaseAddr[tmu], lod_min, lod_max, tmu);
+ lod_min = MIN(lod_min, 8);
+ lod_max = MIN(lod_max, 8);
+ for (lod = lod_min; lod <= lod_max; lod++)
+ {
+ uint32_t *base = &voodoo->texture_cache[tmu][c].data[texture_offset[lod]];
+ uint32_t tex_addr = params->tex_base[tmu][lod] & voodoo->texture_mask;
+ int x, y;
+ int shift = 8 - params->tex_lod[tmu][lod];
+ rgba_u *pal;
+
+ //pclog(" LOD %i : %08x - %08x %i %i,%i\n", lod, params->tex_base[tmu][lod] & voodoo->texture_mask, addr, voodoo->params.tformat[tmu], voodoo->params.tex_w_mask[tmu][lod],voodoo->params.tex_h_mask[tmu][lod]);
+
+
+ switch (params->tformat[tmu])
+ {
+ case TEX_RGB332:
+ for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
+ {
+ for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
+ {
+ uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
+
+ base[x] = makergba(rgb332[dat].r, rgb332[dat].g, rgb332[dat].b, 0xff);
+ }
+ tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
+ base += (1 << shift);
+ }
+ break;
+
+ case TEX_Y4I2Q2:
+ pal = voodoo->ncc_lookup[tmu][(voodoo->params.textureMode[tmu] & TEXTUREMODE_NCC_SEL) ? 1 : 0];
+ for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
+ {
+ for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
+ {
+ uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
+
+ base[x] = makergba(pal[dat].rgba.r, pal[dat].rgba.g, pal[dat].rgba.b, 0xff);
+ }
+ tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
+ base += (1 << shift);
+ }
+ break;
+
+ case TEX_A8:
+ for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
+ {
+ for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
+ {
+ uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
+
+ base[x] = makergba(dat, dat, dat, dat);
+ }
+ tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
+ base += (1 << shift);
+ }
+ break;
+
+ case TEX_I8:
+ for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
+ {
+ for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
+ {
+ uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
+
+ base[x] = makergba(dat, dat, dat, 0xff);
+ }
+ tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
+ base += (1 << shift);
+ }
+ break;
+
+ case TEX_AI8:
+ for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
+ {
+ for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
+ {
+ uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
+
+ base[x] = makergba((dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0xf0) | ((dat >> 4) & 0x0f));
+ }
+ tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
+ base += (1 << shift);
+ }
+ break;
+
+ case TEX_PAL8:
+ pal = voodoo->palette[tmu];
+ for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
+ {
+ for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
+ {
+ uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
+
+ base[x] = makergba(pal[dat].rgba.r, pal[dat].rgba.g, pal[dat].rgba.b, 0xff);
+ }
+ tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
+ base += (1 << shift);
+ }
+ break;
+
+ case TEX_APAL8:
+ pal = voodoo->palette[tmu];
+ for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
+ {
+ for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
+ {
+ uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
+
+ int r = ((pal[dat].rgba.r & 3) << 6) | ((pal[dat].rgba.g & 0xf0) >> 2) | (pal[dat].rgba.r & 3);
+ int g = ((pal[dat].rgba.g & 0xf) << 4) | ((pal[dat].rgba.b & 0xc0) >> 4) | ((pal[dat].rgba.g & 0xf) >> 2);
+ int b = ((pal[dat].rgba.b & 0x3f) << 2) | ((pal[dat].rgba.b & 0x30) >> 4);
+ int a = (pal[dat].rgba.r & 0xfc) | ((pal[dat].rgba.r & 0xc0) >> 6);
+
+ base[x] = makergba(r, g, b, a);
+ }
+ tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
+ base += (1 << shift);
+ }
+ break;
+
+ case TEX_ARGB8332:
+ for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
+ {
+ for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
+ {
+ uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
+
+ base[x] = makergba(rgb332[dat & 0xff].r, rgb332[dat & 0xff].g, rgb332[dat & 0xff].b, dat >> 8);
+ }
+ tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
+ base += (1 << shift);
+ }
+ break;
+
+ case TEX_A8Y4I2Q2:
+ pal = voodoo->ncc_lookup[tmu][(voodoo->params.textureMode[tmu] & TEXTUREMODE_NCC_SEL) ? 1 : 0];
+ for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
+ {
+ for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
+ {
+ uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
+
+ base[x] = makergba(pal[dat & 0xff].rgba.r, pal[dat & 0xff].rgba.g, pal[dat & 0xff].rgba.b, dat >> 8);
+ }
+ tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
+ base += (1 << shift);
+ }
+ break;
+
+ case TEX_R5G6B5:
+ for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
+ {
+ for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
+ {
+ uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
+
+ base[x] = makergba(rgb565[dat].r, rgb565[dat].g, rgb565[dat].b, 0xff);
+ }
+ tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
+ base += (1 << shift);
+ }
+ break;
+
+ case TEX_ARGB1555:
+ for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
+ {
+ for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
+ {
+ uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
+
+ base[x] = makergba(argb1555[dat].r, argb1555[dat].g, argb1555[dat].b, argb1555[dat].a);
+ }
+ tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
+ base += (1 << shift);
+ }
+ break;
+
+ case TEX_ARGB4444:
+ for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
+ {
+ for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
+ {
+ uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
+
+ base[x] = makergba(argb4444[dat].r, argb4444[dat].g, argb4444[dat].b, argb4444[dat].a);
+ }
+ tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
+ base += (1 << shift);
+ }
+ break;
+
+ case TEX_A8I8:
+ for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
+ {
+ for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
+ {
+ uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
+
+ base[x] = makergba(dat & 0xff, dat & 0xff, dat & 0xff, dat >> 8);
+ }
+ tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
+ base += (1 << shift);
+ }
+ break;
+
+ case TEX_APAL88:
+ pal = voodoo->palette[tmu];
+ for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
+ {
+ for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
+ {
+ uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
+
+ base[x] = makergba(pal[dat & 0xff].rgba.r, pal[dat & 0xff].rgba.g, pal[dat & 0xff].rgba.b, dat >> 8);
+ }
+ tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
+ base += (1 << shift);
+ }
+ break;
+
+ default:
+ fatal("Unknown texture format %i\n", params->tformat[tmu]);
+ }
+ }
+
+ voodoo->texture_cache[tmu][c].is16 = voodoo->params.tformat[tmu] & 8;
+
+ if (params->tformat[tmu] == TEX_PAL8 || params->tformat[tmu] == TEX_APAL8 || params->tformat[tmu] == TEX_APAL88)
+ voodoo->texture_cache[tmu][c].palette_checksum = palette_checksum;
+ else
+ voodoo->texture_cache[tmu][c].palette_checksum = 0;
+
+ if (lod_min == 0)
+ {
+ voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->params.tex_base[tmu][0];
+ voodoo->texture_cache[tmu][c].addr_end[0] = voodoo->params.tex_end[tmu][0];
+ }
+ else
+ voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->texture_cache[tmu][c].addr_end[0] = 0;
+
+ if (lod_min <= 1 && lod_max >= 1)
+ {
+ voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->params.tex_base[tmu][1];
+ voodoo->texture_cache[tmu][c].addr_end[1] = voodoo->params.tex_end[tmu][1];
+ }
+ else
+ voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->texture_cache[tmu][c].addr_end[1] = 0;
+
+ if (lod_min <= 2 && lod_max >= 2)
+ {
+ voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->params.tex_base[tmu][2];
+ voodoo->texture_cache[tmu][c].addr_end[2] = voodoo->params.tex_end[tmu][2];
+ }
+ else
+ voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->texture_cache[tmu][c].addr_end[2] = 0;
+
+ if (lod_max >= 3)
+ {
+ voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->params.tex_base[tmu][(lod_min > 3) ? lod_min : 3];
+ voodoo->texture_cache[tmu][c].addr_end[3] = voodoo->params.tex_end[tmu][(lod_max < 8) ? lod_max : 8];
+ }
+ else
+ voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->texture_cache[tmu][c].addr_end[3] = 0;
+
+
+ for (d = 0; d < 4; d++)
+ {
+ addr = voodoo->texture_cache[tmu][c].addr_start[d];
+ addr_end = voodoo->texture_cache[tmu][c].addr_end[d];
+
+ if (addr_end != 0)
+ {
+ for (; addr <= addr_end; addr += (1 << TEX_DIRTY_SHIFT))
+ voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1;
+ }
+ }
+
+ params->tex_entry[tmu] = c;
+ voodoo->texture_cache[tmu][c].refcount++;
+}
+
+void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu)
+{
+ int wait_for_idle = 0;
+ int c;
+
+ memset(voodoo->texture_present[tmu], 0, sizeof(voodoo->texture_present[0]));
+// pclog("Evict %08x %i\n", dirty_addr, sizeof(voodoo->texture_present));
+ for (c = 0; c < TEX_CACHE_MAX; c++)
+ {
+ if (voodoo->texture_cache[tmu][c].base != -1)
+ {
+ int d;
+
+ for (d = 0; d < 4; d++)
+ {
+ int addr_start = voodoo->texture_cache[tmu][c].addr_start[d];
+ int addr_end = voodoo->texture_cache[tmu][c].addr_end[d];
+
+ if (addr_end != 0)
+ {
+ int addr_start_masked = addr_start & voodoo->texture_mask & ~0x3ff;
+ int addr_end_masked = ((addr_end & voodoo->texture_mask) + 0x3ff) & ~0x3ff;
+
+ if (addr_end_masked < addr_start_masked)
+ addr_end_masked = voodoo->texture_mask+1;
+ if (dirty_addr >= addr_start_masked && dirty_addr < addr_end_masked)
+ {
+// pclog(" Evict texture %i %08x\n", c, voodoo->texture_cache[tmu][c].base);
+
+ if (voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[0] ||
+ (voodoo->render_threads == 2 && voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[1]))
+ wait_for_idle = 1;
+
+ voodoo->texture_cache[tmu][c].base = -1;
+ }
+ else
+ {
+ for (; addr_start <= addr_end; addr_start += (1 << TEX_DIRTY_SHIFT))
+ voodoo->texture_present[tmu][(addr_start & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1;
+ }
+ }
+ }
+ }
+ }
+ if (wait_for_idle)
+ voodoo_wait_for_render_thread_idle(voodoo);
+}
+
+void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p)
+{
+ int lod, s, t;
+ voodoo_t *voodoo = (voodoo_t *)p;
+ int tmu;
+
+ if (addr & 0x400000)
+ return; /*TREX != 0*/
+
+ tmu = (addr & 0x200000) ? 1 : 0;
+
+ if (tmu && !voodoo->dual_tmus)
+ return;
+
+ if (voodoo->type < VOODOO_BANSHEE)
+ {
+ if (!(voodoo->params.tformat[tmu] & 8) && voodoo->type >= VOODOO_BANSHEE)
+ {
+ lod = (addr >> 16) & 0xf;
+ t = (addr >> 8) & 0xff;
+ }
+ else
+ {
+ lod = (addr >> 17) & 0xf;
+ t = (addr >> 9) & 0xff;
+ }
+ if (voodoo->params.tformat[tmu] & 8)
+ s = (addr >> 1) & 0xfe;
+ else
+ {
+ if ((voodoo->params.textureMode[tmu] & (1 << 31)) || voodoo->type >= VOODOO_BANSHEE)
+ s = addr & 0xfc;
+ else
+ s = (addr >> 1) & 0xfc;
+ }
+ if (lod > LOD_MAX)
+ return;
+
+// if (addr >= 0x200000)
+// return;
+
+ if (voodoo->params.tformat[tmu] & 8)
+ addr = voodoo->params.tex_base[tmu][lod] + s*2 + (t << voodoo->params.tex_shift[tmu][lod])*2;
+ else
+ addr = voodoo->params.tex_base[tmu][lod] + s + (t << voodoo->params.tex_shift[tmu][lod]);
+ }
+ else
+ addr = (addr & 0x1ffffc) + voodoo->params.tex_base[tmu][0];
+
+ if (voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT])
+ {
+// pclog("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT);
+ flush_texture_cache(voodoo, addr & voodoo->texture_mask, tmu);
+ }
+ if (voodoo->type == VOODOO_3 && voodoo->texture_present[tmu^1][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT])
+ {
+// pclog("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT);
+ flush_texture_cache(voodoo, addr & voodoo->texture_mask, tmu^1);
+ }
+ *(uint32_t *)(&voodoo->tex_mem[tmu][addr & voodoo->texture_mask]) = val;
+}
diff --git a/src/vid_voodoo_texture.h b/src/vid_voodoo_texture.h
new file mode 100644
index 0000000..e4c5602
--- /dev/null
+++ b/src/vid_voodoo_texture.h
@@ -0,0 +1,19 @@
+static const uint32_t texture_offset[LOD_MAX+3] =
+{
+ 0,
+ 256*256,
+ 256*256 + 128*128,
+ 256*256 + 128*128 + 64*64,
+ 256*256 + 128*128 + 64*64 + 32*32,
+ 256*256 + 128*128 + 64*64 + 32*32 + 16*16,
+ 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8,
+ 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4,
+ 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2,
+ 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2 + 1*1,
+ 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2 + 1*1 + 1
+};
+
+void voodoo_recalc_tex(voodoo_t *voodoo, int tmu);
+void voodoo_use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu);
+void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p);
+void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu);
diff --git a/src/vid_wy700.c b/src/vid_wy700.c
index a19f664..1d80bf5 100644
--- a/src/vid_wy700.c
+++ b/src/vid_wy700.c
@@ -12,7 +12,6 @@
#define WY700_YSIZE 800
void updatewindowsize(int x, int y);
-void loadfont(char *s, int format);
/* The Wyse 700 is an unusual video card. Though it has an MC6845 CRTC, this
diff --git a/src/video.c b/src/video.c
index ab0ff7f..7c53f11 100644
--- a/src/video.c
+++ b/src/video.c
@@ -23,9 +23,12 @@
#include "vid_et4000w32.h"
#include "vid_genius.h"
#include "vid_hercules.h"
+#include "vid_ht216.h"
+#include "vid_im1024.h"
#include "vid_incolor.h"
#include "vid_colorplus.h"
#include "vid_mda.h"
+#include "vid_mga.h"
#include "vid_olivetti_m24.h"
#include "vid_oti037.h"
#include "vid_oti067.h"
@@ -34,9 +37,11 @@
#include "vid_pc1640.h"
#include "vid_pc200.h"
#include "vid_pcjr.h"
+#include "vid_pgc.h"
#include "vid_ps1_svga.h"
#include "vid_s3.h"
#include "vid_s3_virge.h"
+#include "vid_sigma.h"
#include "vid_tandy.h"
#include "vid_tandysl.h"
#include "vid_tgui9440.h"
@@ -45,6 +50,7 @@
#include "vid_wy700.h"
#include "vid_t3100e.h"
#include "vid_t1000.h"
+#include "vid_voodoo_banshee.h"
enum
{
@@ -77,36 +83,53 @@ typedef struct
static VIDEO_CARD video_cards[] =
{
+ {"3DFX Voodoo Banshee (reference)", "banshee", &voodoo_banshee_device, GFX_BANSHEE, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
+ {"3DFX Voodoo 3 2000", "v3_2000", &voodoo_3_2000_device, GFX_VOODOO_3_2000, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
+ {"3DFX Voodoo 3 3000", "v3_3000", &voodoo_3_3000_device, GFX_VOODOO_3_3000, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
+ {"Acumos AVGA2 / Cirrus Logic CL-GD5402", "avga2", &avga2_device, GFX_AVGA2, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
{"ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx", &mach64gx_device, GFX_MACH64GX, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
{"ATI Video Xpression (Mach64 VT2)", "mach64vt2", &mach64vt2_device, GFX_MACH64VT2, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
+ {"ATI EGA Wonder 800+ (ATI-18800)", "egawonder800", &ati_ega_wonder_800_device, GFX_EGAWONDER800, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
{"ATI Korean VGA (ATI-28800)", "ati28800k", &ati28800k_device, GFX_ATIKOREANVGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
{"ATI VGA Charger (ATI-28800)", "ati28800", &ati28800_device, GFX_VGACHARGER, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
{"ATI VGA Edge-16 (ATI-18800)", "ati18800", &ati18800_device, GFX_VGAEDGE16, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
{"CGA", "cga", &cga_device, GFX_CGA, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
+ {"Cirrus Logic CL-GD5428", "cl_gd5428", &gd5428_device, GFX_CL_GD5428, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
{"Cirrus Logic CL-GD5429", "cl_gd5429", &gd5429_device, GFX_CL_GD5429, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
{"Cirrus Logic CL-GD5430", "cl_gd5430", &gd5430_device, GFX_CL_GD5430, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
{"Cirrus Logic CL-GD5434", "cl_gd5434", &gd5434_device, GFX_CL_GD5434, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
{"Compaq CGA", "compaq_cga", &compaq_cga_device, GFX_COMPAQ_CGA, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
+ {"Creative Labs 3D Blaster Banshee PCI", "cl_banshee", &creative_voodoo_banshee_device, GFX_CL_BANSHEE, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
{"Diamond Stealth 32 (Tseng ET4000/w32p)", "stealth32", &et4000w32p_device, GFX_ET4000W32, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}},
{"Diamond Stealth 3D 2000 (S3 ViRGE)", "stealth3d_2000", &s3_virge_device, GFX_VIRGE, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}},
{"EGA", "ega", &ega_device, GFX_EGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
{"Hercules", "hercules", &hercules_device, GFX_HERCULES, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
{"Hercules InColor", "incolor", &incolor_device, GFX_INCOLOR, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
+ {"IBM 1MB SVGA Adapter/A (CL GD5428)", "ibm1mbsvga", &ibm_gd5428_device, GFX_IBM_GD5428, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}},
+ {"Image Manager 1024", "im1024", &im1024_device, GFX_IM1024, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
+ {"Kasan Hangulmadang-16 (Tseng ET4000AX)", "kasan16", &et4000_kasan_device, GFX_KASAN16VGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
+ {"Matrox Mystique", "mystique", &mystique_device, GFX_MYSTIQUE, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}},
{"MDA", "mda", &mda_device, GFX_MDA, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
- {"MDSI Genius", "genius", &genius_device, GFX_GENIUS, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
+ {"MDSI Genius", "genius", &genius_device, GFX_GENIUS, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
{"Number Nine 9FX (S3 Trio64)", "n9_9fx", &s3_9fx_device, GFX_N9_9FX, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}},
{"OAK OTI-037", "oti037", &oti037_device, GFX_OTI037, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}},
{"OAK OTI-067", "oti067", &oti067_device, GFX_OTI067, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}},
{"Olivetti GO481 (Paradise PVGA1A)", "olivetti_go481", ¶dise_pvga1a_oli_go481_device, GFX_OLIVETTI_GO481, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}},
{"Paradise Bahamas 64 (S3 Vision864)", "bahamas64", &s3_bahamas64_device, GFX_BAHAMAS64, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 5, 20, 20, 35}},
+/* Not offered as the emulation is very incomplete
+ {"Professional Graphics Controller", "pgc", &pgc_device, GFX_PGC, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
+*/
{"Phoenix S3 Trio32", "px_trio32", &s3_phoenix_trio32_device, GFX_PHOENIX_TRIO32, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}},
{"Phoenix S3 Trio64", "px_trio64", &s3_phoenix_trio64_device, GFX_PHOENIX_TRIO64, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}},
{"Plantronics ColorPlus", "plantronics", &colorplus_device, GFX_COLORPLUS, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
{"S3 ViRGE/DX", "virge375", &s3_virge_375_device, GFX_VIRGEDX, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}},
+ {"Sigma Color 400", "sigma400", &sigma_device, GFX_SIGMA400, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
{"Trident TVGA8900D", "tvga8900d", &tvga8900d_device, GFX_TVGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 8, 8, 12}},
- {"Tseng ET4000AX", "et4000ax", &et4000_device, GFX_ET4000, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
+ {"Trident TVGA9000B", "tvga9000b", &tvga9000b_device, GFX_TVGA9000B, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 7, 7, 12, 7, 7, 12}},
{"Trident TGUI9400CXi", "tgui9400cxi", &tgui9400cxi_device, GFX_TGUI9400CXI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 8, 16, 4, 8, 16}},
{"Trident TGUI9440", "tgui9440", &tgui9440_device, GFX_TGUI9440, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 8, 16, 4, 8, 16}},
+ {"Trigem Korean VGA (Tseng ET4000AX)", "tgkorvga", &et4000k_device, GFX_TGKOREANVGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
+ {"Tseng ET4000AX", "et4000ax", &et4000_device, GFX_ET4000, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
{"VGA", "vga", &vga_device, GFX_VGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
{"Wyse 700", "wy700", &wy700_device, GFX_WY700, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}},
{"", "", NULL, 0}
@@ -119,12 +142,15 @@ static video_timings_t timing_pc200 = {VIDEO_ISA, 8,16,32, 8,16,32};
static video_timings_t timing_m24 = {VIDEO_ISA, 8,16,32, 8,16,32};
static video_timings_t timing_pvga1a = {VIDEO_ISA, 6, 8,16, 6, 8,16};
static video_timings_t timing_wd90c11 = {VIDEO_ISA, 3, 3, 6, 5, 5,10};
+static video_timings_t timing_avga2 = {VIDEO_ISA, 3, 3, 6, 5, 5,10};
static video_timings_t timing_oti067 = {VIDEO_ISA, 6, 8,16, 6, 8,16};
static video_timings_t timing_vga = {VIDEO_ISA, 8,16,32, 8,16,32};
static video_timings_t timing_ps1_svga = {VIDEO_ISA, 6, 8,16, 6, 8,16};
static video_timings_t timing_t3100e = {VIDEO_ISA, 8,16,32, 8,16,32};
static video_timings_t timing_t1000 = {VIDEO_ISA, 8,16,32, 8,16,32};
+static video_timings_t timing_spc4620p = {VIDEO_ISA, 2, 2, 4, 4, 4, 8};
static video_timings_t timing_pc425x = {VIDEO_BUS, 5, 5, 9, 20,20,30};
+static video_timings_t timing_pb410a = {VIDEO_BUS, 5, 5, 9, 20,20,30};
static video_timings_t timing_pb570 = {VIDEO_BUS, 4, 4, 8, 10,10,20};
static video_timings_t timing_pb520r = {VIDEO_BUS, 4, 4, 8, 10,10,20};
@@ -146,7 +172,7 @@ char *video_card_getname(int card)
return video_cards[card].name;
}
-device_t *video_card_getdevice(int card)
+device_t *video_card_getdevice(int card, int romset)
{
switch (romset)
{
@@ -164,46 +190,71 @@ device_t *video_card_getdevice(int card)
return &pc1512_device;
case ROM_PC1640:
- if (gfxcard == GFX_BUILTIN)
+ if (card == GFX_BUILTIN)
return &pc1640_device;
break;
case ROM_PC200:
- if (gfxcard == GFX_BUILTIN)
+ if (card == GFX_BUILTIN)
return &pc200_device;
break;
+
+ case ROM_PPC512:
+ if (card == GFX_BUILTIN)
+ return &ppc512_device;
+ break;
case ROM_OLIM24:
return &m24_device;
case ROM_PC2086:
- if (gfxcard == GFX_BUILTIN)
+ if (card == GFX_BUILTIN)
return ¶dise_pvga1a_pc2086_device;
break;
case ROM_PC3086:
- if (gfxcard == GFX_BUILTIN)
+ if (card == GFX_BUILTIN)
return ¶dise_pvga1a_pc3086_device;
break;
case ROM_MEGAPC:
return ¶dise_wd90c11_megapc_device;
-
+
+ case ROM_SPC4620P:
+ if (card == GFX_BUILTIN)
+ return &ati28800k_spc4620p_device;
+ break;
+
+ case ROM_SPC6033P:
+ if (card == GFX_BUILTIN)
+ return &ati28800k_spc6033p_device;
+ break;
+
case ROM_ACER386:
return &oti067_acer386_device;
+
+ case ROM_AMA932J:
+ return &oti067_ama932j_device;
case ROM_IBMPS1_2011:
case ROM_IBMPS2_M30_286:
+ return &ps1vga_device;
+
case ROM_IBMPS2_M50:
case ROM_IBMPS2_M55SX:
case ROM_IBMPS2_M70_TYPE3:
case ROM_IBMPS2_M70_TYPE4:
case ROM_IBMPS2_M80:
- return &ps1vga_device;
-
+ if (card == GFX_BUILTIN)
+ return &ps1vga_device;
+ break;
+
case ROM_IBMPS1_2121:
return &ps1_m2121_svga_device;
+ case ROM_IBMPS1_2133_451:
+ return &gd5426_ps1_device;
+
case ROM_T3100E:
return &t3100e_device;
@@ -214,20 +265,31 @@ device_t *video_card_getdevice(int card)
case ROM_ELX_PC425X:
return &tgui9400cxi_elx_device;
+ case ROM_PB410A:
+ return &ht216_32_pb410a_device;
+
case ROM_PB570:
return &gd5430_pb570_device;
case ROM_PB520R:
return &gd5434_pb520r_device;
+
+ case ROM_CBM_SL386SX25:
+ return &avga2_cbm_sl386sx_device;
}
return video_cards[card].device;
}
-int video_card_has_config(int card)
+int video_card_has_config(int card, int romset)
{
- if (card == GFX_BUILTIN)
+ /* Allow builtin cards to have configuration */
+ device_t *device = video_card_getdevice(card, romset);
+
+ if (!device)
+ {
return 0;
- return video_cards[card].device->config ? 1 : 0;
+ }
+ return device->config ? 1 : 0;
}
int video_card_getid(char *s)
@@ -301,8 +363,16 @@ int video_is_mda()
{
switch (romset)
{
- case ROM_PC1640:
case ROM_PC200:
+ case ROM_PPC512:
+ if (gfxcard == GFX_BUILTIN)
+ {
+/* The chipset here can emulate either CGA or MDA. Find out which */
+ return (pc200_is_mda);
+ }
+ break;
+
+ case ROM_PC1640:
case ROM_PC2086:
case ROM_PC3086:
case ROM_MEGAPC:
@@ -323,11 +393,14 @@ int video_is_mda()
case ROM_IBMPS2_M70_TYPE4:
case ROM_IBMPS2_M80:
case ROM_IBMPS1_2121:
- case ROM_T3100E:
+ case ROM_IBMPS1_2133_451:
+ case ROM_T3100E:
case ROM_T1000:
case ROM_ELX_PC425X:
+ case ROM_PB410A:
case ROM_PB570:
case ROM_PB520R:
+ case ROM_CBM_SL386SX25:
return 0;
}
return (video_cards[video_old_to_new(gfxcard)].flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_MDA;
@@ -337,8 +410,14 @@ int video_is_cga()
switch (romset)
{
case ROM_PC200:
- if (gfxcard != GFX_BUILTIN)
- break;
+ case ROM_PPC512:
+ if (gfxcard == GFX_BUILTIN)
+ {
+/* The chipset here can emulate either CGA or MDA. Find out which */
+ return (!pc200_is_mda);
+ }
+ break;
+
case ROM_IBMPCJR:
case ROM_TANDY:
case ROM_TANDY1000HX:
@@ -364,9 +443,12 @@ int video_is_cga()
case ROM_IBMPS2_M70_TYPE4:
case ROM_IBMPS2_M80:
case ROM_IBMPS1_2121:
+ case ROM_IBMPS1_2133_451:
case ROM_ELX_PC425X:
+ case ROM_PB410A:
case ROM_PB570:
case ROM_PB520R:
+ case ROM_CBM_SL386SX25:
return 0;
}
return (video_cards[video_old_to_new(gfxcard)].flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_CGA;
@@ -381,6 +463,7 @@ int video_is_ega_vga()
case ROM_TANDY1000SL2:
case ROM_PC1512:
case ROM_PC200:
+ case ROM_PPC512:
case ROM_OLIM24:
case ROM_T3100E:
case ROM_T1000:
@@ -391,6 +474,7 @@ int video_is_ega_vga()
case ROM_PC3086:
case ROM_MEGAPC:
case ROM_ACER386:
+ case ROM_AMA932J:
case ROM_IBMPS1_2011:
case ROM_IBMPS2_M30_286:
case ROM_IBMPS2_M50:
@@ -399,9 +483,12 @@ int video_is_ega_vga()
case ROM_IBMPS2_M70_TYPE4:
case ROM_IBMPS2_M80:
case ROM_IBMPS1_2121:
+ case ROM_IBMPS1_2133_451:
case ROM_ELX_PC425X:
+ case ROM_PB410A:
case ROM_PB570:
case ROM_PB520R:
+ case ROM_CBM_SL386SX25:
return 1;
}
return (video_cards[video_old_to_new(gfxcard)].flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_SPECIAL;
@@ -499,6 +586,7 @@ void video_updatetiming()
break;
case ROM_PC200:
+ case ROM_PPC512:
if (gfxcard == GFX_BUILTIN)
timing = &timing_pc200;
break;
@@ -517,26 +605,45 @@ void video_updatetiming()
if (gfxcard == GFX_BUILTIN)
timing = &timing_wd90c11;
break;
+
+ case ROM_SPC4620P:
+ case ROM_SPC6033P:
+ if (gfxcard == GFX_BUILTIN)
+ timing = &timing_spc4620p;
+ break;
case ROM_ACER386:
if (gfxcard == GFX_BUILTIN)
timing = &timing_oti067;
break;
+
+ case ROM_AMA932J:
+ if (gfxcard == GFX_BUILTIN)
+ timing = &timing_oti067;
+ break;
case ROM_IBMPS1_2011:
case ROM_IBMPS2_M30_286:
+ timing = &timing_vga;
+ break;
+
case ROM_IBMPS2_M50:
case ROM_IBMPS2_M55SX:
case ROM_IBMPS2_M70_TYPE3:
case ROM_IBMPS2_M70_TYPE4:
case ROM_IBMPS2_M80:
- timing = &timing_vga;
+ if (gfxcard == GFX_BUILTIN)
+ timing = &timing_vga;
break;
case ROM_IBMPS1_2121:
timing = &timing_ps1_svga;
break;
+ case ROM_IBMPS1_2133_451:
+ timing = &timing_pb570;
+ break;
+
case ROM_T3100E:
timing = &timing_t3100e;
break;
@@ -549,6 +656,11 @@ void video_updatetiming()
timing = &timing_pc425x;
break;
+ case ROM_PB410A:
+ if (gfxcard == GFX_BUILTIN)
+ timing = &timing_pb410a;
+ break;
+
case ROM_PB570:
timing = &timing_pb570;
break;
@@ -556,6 +668,10 @@ void video_updatetiming()
case ROM_PB520R:
timing = &timing_pb520r;
break;
+
+ case ROM_CBM_SL386SX25:
+ timing = &timing_avga2;
+ break;
}
@@ -651,6 +767,14 @@ void video_init()
device_add(&pc200_device);
return;
}
+ break;
+
+ case ROM_PPC512:
+ if (gfxcard == GFX_BUILTIN)
+ {
+ device_add(&ppc512_device);
+ return;
+ }
break;
case ROM_OLIM24:
@@ -680,7 +804,23 @@ void video_init()
return;
}
break;
-
+
+ case ROM_SPC4620P:
+ if (gfxcard == GFX_BUILTIN)
+ {
+ device_add(&ati28800k_spc4620p_device);
+ return;
+ }
+ break;
+
+ case ROM_SPC6033P:
+ if (gfxcard == GFX_BUILTIN)
+ {
+ device_add(&ati28800k_spc6033p_device);
+ return;
+ }
+ break;
+
case ROM_ACER386:
device_add(&oti067_acer386_device);
if (gfxcard != GFX_BUILTIN)
@@ -689,21 +829,34 @@ void video_init()
break;
}
return;
+
+ case ROM_AMA932J:
+ device_add(&oti067_ama932j_device);
+ return;
case ROM_IBMPS1_2011:
case ROM_IBMPS2_M30_286:
+ device_add(&ps1vga_device);
+ return;
+
case ROM_IBMPS2_M50:
case ROM_IBMPS2_M55SX:
case ROM_IBMPS2_M70_TYPE3:
case ROM_IBMPS2_M70_TYPE4:
case ROM_IBMPS2_M80:
device_add(&ps1vga_device);
- return;
+ if (gfxcard == GFX_BUILTIN)
+ return;
+ break;
case ROM_IBMPS1_2121:
device_add(&ps1_m2121_svga_device);
return;
+ case ROM_IBMPS1_2133_451:
+ device_add(&gd5426_ps1_device);
+ return;
+
case ROM_T3100E:
device_add(&t3100e_device);
return;
@@ -717,6 +870,15 @@ void video_init()
device_add(&tgui9400cxi_elx_device);
return;
+ case ROM_PB410A:
+ device_add(&ht216_32_pb410a_device);
+ if (gfxcard != GFX_BUILTIN)
+ {
+ svga_set_override(svga_get_pri(), 1);
+ break;
+ }
+ return;
+
case ROM_PB570:
device_add(&gd5430_pb570_device);
if (gfxcard != GFX_BUILTIN)
@@ -734,6 +896,10 @@ void video_init()
break;
}
return;
+
+ case ROM_CBM_SL386SX25:
+ device_add(&avga2_cbm_sl386sx_device);
+ return;
}
device_add(video_cards[video_old_to_new(gfxcard)].device);
}
@@ -745,12 +911,13 @@ uint8_t fontdat[2048][8];
uint8_t fontdatm[2048][16];
uint8_t fontdatw[512][32]; /* Wyse700 font */
uint8_t fontdat8x12[256][16]; /* MDSI Genius font */
+uint8_t fontdat12x18[256][36]; /* IM1024 font */
uint8_t fontdatksc5601[16384][32]; /* Korean KSC-5601 font */
uint8_t fontdatksc5601_user[192][32]; /* Korean KSC-5601 user defined font */
int xsize=1,ysize=1;
-void loadfont(char *s, int format)
+void loadfont(char *s, fontformat_t format)
{
FILE *f=romfopen(s,"rb");
int c,d;
@@ -762,7 +929,7 @@ void loadfont(char *s, int format)
}
switch (format)
{
- case 0: /* MDA */
+ case FONT_MDA: /* MDA */
for (c=0;c<256;c++)
{
for (d=0;d<8;d++)
@@ -786,33 +953,22 @@ void loadfont(char *s, int format)
}
}
break;
- case 1: /* PC200 */
- for (c=0;c<256;c++)
- {
- for (d=0;d<8;d++)
+ case FONT_PC200: /* PC200 */
+ for (d=0;d<4;d++) /* There are 4 fonts in the ROM */
+ {
+ for (c=0;c<256;c++) /* 8x14 MDA in 8x16 cell */
+ {
+ fread(&fontdatm[256*d+c], 1, 16, f);
+ }
+ for (c=0;c<256; c++) /* 8x8 CGA in 8x16 cell */
{
- fontdatm[c][d]=getc(f);
+ fread(fontdat[256*d+c], 1, 8, f);
+ fseek(f, 8, SEEK_CUR);
}
}
- for (c=0;c<256;c++)
- {
- for (d=0;d<8;d++)
- {
- fontdatm[c][d+8]=getc(f);
- }
- }
- fseek(f, 4096, SEEK_SET);
- for (c=0;c<256;c++)
- {
- for (d=0;d<8;d++)
- {
- fontdat[c][d]=getc(f);
- }
- for (d=0;d<8;d++) getc(f);
- }
break;
default:
- case 2: /* CGA */
+ case FONT_CGA: /* CGA */
for (c=0;c<2048;c++) /* Allow up to 2048 chars */
{
for (d=0;d<8;d++)
@@ -821,7 +977,7 @@ void loadfont(char *s, int format)
}
}
break;
- case 3: /* Wyse 700 */
+ case FONT_WY700: /* Wyse 700 */
for (c=0;c<512;c++)
{
for (d=0;d<32;d++)
@@ -830,7 +986,7 @@ void loadfont(char *s, int format)
}
}
break;
- case 4: /* MDSI Genius */
+ case FONT_MDSI: /* MDSI Genius */
for (c=0;c<256;c++)
{
for (d=0;d<16;d++)
@@ -839,7 +995,7 @@ void loadfont(char *s, int format)
}
}
break;
- case 5: /* Toshiba 3100e */
+ case FONT_T3100E: /* Toshiba 3100e */
for (d = 0; d < 2048; d += 512) /* Four languages... */
{
for (c = d; c < d+256; c++)
@@ -869,7 +1025,7 @@ void loadfont(char *s, int format)
}
}
break;
- case 6: /* Korean KSC-5601 */
+ case FONT_KSC5601: /* Korean KSC-5601 */
for (c=0;c<16384;c++)
{
for (d=0;d<32;d++)
@@ -878,6 +1034,25 @@ void loadfont(char *s, int format)
}
}
break;
+ case FONT_SIGMA400: /* Sigma Color 400 */
+ /* The first 4k of the character ROM holds an 8x8 font */
+ for (c = 0; c < 256; c++)
+ {
+ fread(&fontdat[c][0], 1, 8, f);
+ fseek(f, 8, SEEK_CUR);
+ }
+ /* The second 4k holds an 8x16 font */
+ for (c = 0; c < 256; c++)
+ {
+ fread(&fontdatm[c][0], 1, 16, f);
+ }
+ break;
+ case FONT_IM1024: /* Image Manager 1024 native font */
+ for (c=0;c<256;c++)
+ {
+ fread(&fontdat12x18[c][0], 1, 36, f);
+ }
+ break;
}
fclose(f);
diff --git a/src/video.h b/src/video.h
index f8edf05..459abcb 100644
--- a/src/video.h
+++ b/src/video.h
@@ -23,8 +23,8 @@ extern BITMAP *buffer32;
int video_card_available(int card);
char *video_card_getname(int card);
-struct device_t *video_card_getdevice(int card);
-int video_card_has_config(int card);
+struct device_t *video_card_getdevice(int card, int romset);
+int video_card_has_config(int card, int romset);
int video_card_getid(char *s);
int video_old_to_new(int card);
int video_new_to_old(int card);
@@ -82,7 +82,21 @@ extern int vid_resize;
void video_wait_for_blit();
void video_wait_for_buffer();
-void loadfont(char *s, int format);
+
+typedef enum
+{
+ FONT_MDA, /* MDA 8x14 */
+ FONT_PC200, /* MDA 8x14 and CGA 8x8, four fonts */
+ FONT_CGA, /* CGA 8x8, two fonts */
+ FONT_WY700, /* Wy700 16x16, two fonts */
+ FONT_MDSI, /* MDSI Genius 8x12 */
+ FONT_T3100E, /* Toshiba T3100e, four fonts */
+ FONT_KSC5601, /* Korean KSC-5601 */
+ FONT_SIGMA400, /* Sigma Color 400, 8x8 and 8x16 */
+ FONT_IM1024, /* Image Manager 1024 */
+} fontformat_t;
+
+void loadfont(char *s, fontformat_t format);
void initvideo();
void video_init();
diff --git a/src/vl82c480.c b/src/vl82c480.c
new file mode 100644
index 0000000..57bcce5
--- /dev/null
+++ b/src/vl82c480.c
@@ -0,0 +1,169 @@
+#include "ibm.h"
+#include "io.h"
+#include "mem.h"
+#include "vl82c480.h"
+
+static struct
+{
+ int cfg_index;
+ uint8_t cfg_regs[256];
+
+ uint8_t port_92;
+} vl82c480;
+
+#define CFG_ID 0x00
+#define CFG_AAXS 0x0d
+#define CFG_BAXS 0x0e
+#define CFG_CAXS 0x0f
+#define CFG_DAXS 0x10
+#define CFG_EAXS 0x11
+#define CFG_FAXS 0x12
+
+#define ID_VL82C480 0x90
+
+static void shadow_control(uint32_t addr, uint32_t size, int state)
+{
+// pclog("shadow_control: addr=%08x size=%04x state=%i\n", addr, size, state);
+ switch (state)
+ {
+ case 0:
+ mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 1:
+ mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ case 2:
+ mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 3:
+ mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ }
+ flushmmucache_nopc();
+}
+
+void vl82c480_write(uint16_t addr, uint8_t val, void *p)
+{
+// if (addr != 0x92) pclog("vl82c480_write: addr=%04x val=%02x\n", addr, val);
+ switch (addr)
+ {
+ case 0x92:
+ if ((mem_a20_alt ^ val) & 2)
+ {
+ mem_a20_alt = val & 2;
+ mem_a20_recalc();
+ }
+ if ((~vl82c480.port_92 & val) & 1)
+ {
+ softresetx86();
+ cpu_set_edx();
+ }
+ vl82c480.port_92 = val;
+ break;
+
+ case 0xec:
+ vl82c480.cfg_index = val;
+ break;
+
+ case 0xed:
+ if (vl82c480.cfg_index >= 0x01 && vl82c480.cfg_index <= 0x24)
+ {
+ vl82c480.cfg_regs[vl82c480.cfg_index] = val;
+ switch (vl82c480.cfg_index)
+ {
+ case CFG_AAXS:
+ shadow_control(0xa0000, 0x4000, val & 3);
+ shadow_control(0xa4000, 0x4000, (val >> 2) & 3);
+ shadow_control(0xa8000, 0x4000, (val >> 4) & 3);
+ shadow_control(0xac000, 0x4000, (val >> 6) & 3);
+ break;
+ case CFG_BAXS:
+ shadow_control(0xb0000, 0x4000, val & 3);
+ shadow_control(0xb4000, 0x4000, (val >> 2) & 3);
+ shadow_control(0xb8000, 0x4000, (val >> 4) & 3);
+ shadow_control(0xbc000, 0x4000, (val >> 6) & 3);
+ break;
+ case CFG_CAXS:
+ shadow_control(0xc0000, 0x4000, val & 3);
+ shadow_control(0xc4000, 0x4000, (val >> 2) & 3);
+ shadow_control(0xc8000, 0x4000, (val >> 4) & 3);
+ shadow_control(0xcc000, 0x4000, (val >> 6) & 3);
+ break;
+ case CFG_DAXS:
+ shadow_control(0xd0000, 0x4000, val & 3);
+ shadow_control(0xd4000, 0x4000, (val >> 2) & 3);
+ shadow_control(0xd8000, 0x4000, (val >> 4) & 3);
+ shadow_control(0xdc000, 0x4000, (val >> 6) & 3);
+ break;
+ case CFG_EAXS:
+ shadow_control(0xe0000, 0x4000, val & 3);
+ shadow_control(0xe4000, 0x4000, (val >> 2) & 3);
+ shadow_control(0xe8000, 0x4000, (val >> 4) & 3);
+ shadow_control(0xec000, 0x4000, (val >> 6) & 3);
+ break;
+ case CFG_FAXS:
+ shadow_control(0xf0000, 0x4000, val & 3);
+ shadow_control(0xf4000, 0x4000, (val >> 2) & 3);
+ shadow_control(0xf8000, 0x4000, (val >> 4) & 3);
+ shadow_control(0xfc000, 0x4000, (val >> 6) & 3);
+ break;
+ }
+ }
+ break;
+
+ case 0xee:
+ if (mem_a20_alt)
+ {
+ vl82c480.port_92 &= ~2;
+ mem_a20_alt = 0;
+ mem_a20_recalc();
+ }
+ break;
+ }
+}
+
+uint8_t vl82c480_read(uint16_t addr, void *p)
+{
+ uint8_t ret = 0xff;
+
+ switch (addr)
+ {
+ case 0x92:
+ ret = vl82c480.port_92;
+ break;
+
+ case 0xec:
+ ret = vl82c480.cfg_index;
+ break;
+
+ case 0xed:
+ ret = vl82c480.cfg_regs[vl82c480.cfg_index];
+ break;
+
+ case 0xee:
+ if (!mem_a20_alt)
+ {
+ vl82c480.port_92 |= 2;
+ mem_a20_alt = 1;
+ mem_a20_recalc();
+ }
+ break;
+
+ case 0xef:
+ softresetx86();
+ cpu_set_edx();
+ break;
+ }
+
+// pclog("vl82c480_read: addr=%04x ret=%02x\n", addr, ret);
+ return ret;
+}
+
+void vl82c480_init(void)
+{
+ memset(&vl82c480, 0, sizeof(vl82c480));
+ vl82c480.cfg_regs[CFG_ID] = ID_VL82C480;
+
+ io_sethandler(0x0092, 0x0001, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, NULL);
+ io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, NULL);
+}
diff --git a/src/vl82c480.h b/src/vl82c480.h
new file mode 100644
index 0000000..07cf6f7
--- /dev/null
+++ b/src/vl82c480.h
@@ -0,0 +1 @@
+void vl82c480_init(void);
diff --git a/src/vt82c586b.c b/src/vt82c586b.c
index 2540d5c..1235317 100644
--- a/src/vt82c586b.c
+++ b/src/vt82c586b.c
@@ -28,6 +28,16 @@ static struct
struct
{
uint16_t io_base;
+
+ uint16_t pm_status;
+ uint16_t pm_enable;
+ uint16_t pm_ctrl;
+
+ uint16_t gbl_status;
+ uint16_t gbl_enable;
+ uint16_t gbl_ctrl;
+
+ uint8_t smi_cmd;
} power;
} vt82c586b;
@@ -36,6 +46,12 @@ static struct
#define ACPI_IO_ENABLE (1 << 7)
#define ACPI_TIMER_32BIT (1 << 3)
+#define GBL_SW_SMI_STS (1 << 6)
+#define GBL_SW_SMI_EN (1 << 6)
+
+#define PM_CTRL_SLP_EN (1 << 13)
+#define PM_CTRL_SLP_TYP_MASK (7 << 10)
+
static uint8_t vt82c586b_read(int func, int addr, void *priv)
{
switch (func)
@@ -235,21 +251,110 @@ static void vt82c586b_usb_write(int addr, uint8_t val)
static uint8_t power_reg_read(uint16_t addr, void *p)
{
uint32_t timer;
+ uint8_t ret = 0xff;
switch (addr & 0xff)
{
+ case 0x00: case 0x01:
+ ret = vt82c586b.power.pm_status >> ((addr & 1) * 8);
+ break;
+ case 0x02: case 0x03:
+ ret = vt82c586b.power.pm_enable >> ((addr & 1) * 8);
+ break;
+ case 0x04: case 0x05:
+ ret = vt82c586b.power.pm_ctrl >> ((addr & 1) * 8);
+ break;
+
case 0x08: case 0x09: case 0x0a: case 0x0b: /*ACPI timer*/
timer = (tsc * ACPI_TIMER_FREQ) / cpu_get_speed();
if (!(vt82c586b.power_regs[0x41] & ACPI_TIMER_32BIT))
timer &= 0x00ffffff;
return (timer >> (8 * (addr & 3))) & 0xff;
+
+ case 0x28: case 0x29:
+ ret = vt82c586b.power.gbl_status >> ((addr & 1) * 8);
+ break;
+ case 0x2a: case 0x2b:
+ ret = vt82c586b.power.gbl_enable >> ((addr & 1) * 8);
+ break;
+ case 0x2c: case 0x2d:
+ ret = vt82c586b.power.gbl_ctrl >> ((addr & 1) * 8);
+ break;
+
+ case 0x2f:
+ ret = vt82c586b.power.smi_cmd;
+ break;
}
-// pclog("power_reg_read: addr=%04x\n", addr);
- return 0xff;
+// pclog("power_reg_read: addr=%04x ret=%02x\n", addr, ret);
+ return ret;
}
static void power_reg_write(uint16_t addr, uint8_t val, void *p)
{
// pclog("power_reg_write: addr=%04x val=%02x\n", addr, val);
+ switch (addr & 0xff)
+ {
+ case 0x00:
+ vt82c586b.power.pm_status &= ~(val & 0x31);
+ break;
+ case 0x01:
+ vt82c586b.power.pm_status &= ~((val & 0x8d) << 8);
+ break;
+
+ case 0x02:
+ vt82c586b.power.pm_enable = (vt82c586b.power.pm_enable & ~0xff) | (val & 0x21);
+ break;
+ case 0x03:
+ vt82c586b.power.pm_enable = (vt82c586b.power.pm_enable & ~0xff00) | ((val & 0x05) << 8);
+ break;
+
+ case 0x04:
+ vt82c586b.power.pm_ctrl = (vt82c586b.power.pm_ctrl & ~0xff) | (val & 0x07);
+ if (val & (1 << 2))
+ pclog("VT82C586B set GBL_RLS\n");
+ break;
+ case 0x05:
+ vt82c586b.power.pm_ctrl = (vt82c586b.power.pm_ctrl & ~0xff00) | ((val & 0x1c) << 8);
+ /*Note: PM_CTRL_SLP_EN is write-only, hence not stored in pm_ctrl*/
+ if (val & (PM_CTRL_SLP_EN >> 8))
+ {
+ pclog("VT82C586B transition to power state %i\n", (val >> 2) & 7);
+ if (!(vt82c586b.power.pm_ctrl & PM_CTRL_SLP_TYP_MASK))
+ {
+ pclog("Power off\n");
+ stop_emulation_now();
+ }
+ }
+ break;
+
+ case 0x28:
+ vt82c586b.power.gbl_status &= ~(val & 0x7f);
+ break;
+
+ case 0x2a:
+ vt82c586b.power.gbl_enable = (vt82c586b.power.gbl_enable & ~0xff) | (val & 0x7f);
+ break;
+
+ case 0x2c:
+ vt82c586b.power.gbl_ctrl = (vt82c586b.power.gbl_ctrl & ~0xff) | (val & 0x17);
+ if (val & (1 << 1))
+ pclog("VT82C586B set BIOS_RLS\n");
+ break;
+ case 0x2d:
+ if (val & 1)
+ vt82c586b.power.gbl_ctrl &= ~0x100;
+ break;
+
+ case 0x2f:
+ vt82c586b.power.smi_cmd = val;
+ vt82c586b.power_regs[0x47] = val;
+ if (vt82c586b.power.gbl_enable & GBL_SW_SMI_EN)
+ {
+ vt82c586b.power.gbl_status |= GBL_SW_SMI_STS;
+ x86_smi_trigger();
+ }
+ pclog("SMI_CMD write %02x\n", val);
+ break;
+ }
}
static void vt82c586b_power_write(int addr, uint8_t val)
{
diff --git a/src/w83877tf.c b/src/w83877tf.c
index 78c2a63..bc4dccc 100644
--- a/src/w83877tf.c
+++ b/src/w83877tf.c
@@ -6,12 +6,20 @@
#include "serial.h"
#include "w83877tf.h"
+enum
+{
+ CHIP_W83877F,
+ CHIP_W83877TF
+};
+
typedef struct w83877tf_t
{
int enable_regs;
uint8_t key[2];
+ uint8_t unlock_key;
int index;
uint8_t regs[256];
+ int chip;
} w83877tf_t;
static w83877tf_t w83877tf_global;
@@ -26,6 +34,13 @@ static void w83877tf_write_reg(w83877tf_t *w83877tf, int index, uint8_t val)
// pclog("w83877tf_write: index=%02x val=%02x\n", index, val);
switch (index)
{
+ case 0x0c:
+ if (w83877tf->regs[0x16] & 1)
+ w83877tf->unlock_key = (val & (1 << 5)) ? 0x87 : 0x86;
+ else
+ w83877tf->unlock_key = (val & (1 << 5)) ? 0x89 : 0x88;
+ break;
+
case 0x16:
if (val == 2) /*Written by VA-503+ BIOS. Apparently should not change IO mapping*/
return;
@@ -33,9 +48,15 @@ static void w83877tf_write_reg(w83877tf_t *w83877tf, int index, uint8_t val)
io_removehandler(0x0250, 0x0003, w83877tf_read_25x, NULL, NULL, w83877tf_write_25x, NULL, NULL, &w83877tf_global);
io_removehandler(0x03f0, 0x0002, w83877tf_read_3fx, NULL, NULL, w83877tf_write_3fx, NULL, NULL, &w83877tf_global);
if (val & 0x01)
+ {
io_sethandler(0x03f0, 0x0002, w83877tf_read_3fx, NULL, NULL, w83877tf_write_3fx, NULL, NULL, &w83877tf_global);
+ w83877tf->unlock_key = (w83877tf->regs[0xc] & (1 << 5)) ? 0x87 : 0x86;
+ }
else
+ {
io_sethandler(0x0250, 0x0003, w83877tf_read_25x, NULL, NULL, w83877tf_write_25x, NULL, NULL, &w83877tf_global);
+ w83877tf->unlock_key = (w83877tf->regs[0xc] & (1 << 5)) ? 0x89 : 0x88;
+ }
if ((w83877tf->regs[0x16] & 4) && !(val & 4))
{
@@ -81,7 +102,14 @@ static uint8_t w83877tf_read_reg(w83877tf_t *w83877tf, int index)
switch (w83877tf->index)
{
case 0x09:
- return 0x0c; /*W83877TF ID*/
+ switch (w83877tf->chip)
+ {
+ case CHIP_W83877F:
+ return 0x0a; /*W83877F ID*/
+ case CHIP_W83877TF:
+ return 0x0c; /*W83877TF ID*/
+ }
+ break;
}
return w83877tf->regs[index];
}
@@ -95,7 +123,7 @@ static void w83877tf_write_25x(uint16_t port, uint8_t val, void *p)
switch (port)
{
case 0x250: /*Enable register*/
- w83877tf->enable_regs = (val == 0x89) ? 1 : 0;
+ w83877tf->enable_regs = (val == w83877tf->unlock_key) ? 1 : 0;
break;
case 0x251: /*Index*/
if (w83877tf->enable_regs)
@@ -138,12 +166,19 @@ static void w83877tf_write_3fx(uint16_t port, uint8_t val, void *p)
{
case 0x3f0: /*Enable/index register*/
if (val == 0xaa)
+ {
+ fdc_3f1_enable(1);
w83877tf->enable_regs = 0;
+ }
else if (!w83877tf->enable_regs)
{
w83877tf->key[1] = w83877tf->key[0];
w83877tf->key[0] = val;
- w83877tf->enable_regs = (w83877tf->key[0] == 0x87 && w83877tf->key[1] == 0x87);
+ w83877tf->enable_regs = (w83877tf->key[0] == w83877tf->unlock_key && w83877tf->key[1] == w83877tf->unlock_key);
+ /*The FDC conflicts with the 3fx config registers, so disable
+ it when enabling config registers*/
+ if (w83877tf->enable_regs)
+ fdc_3f1_enable(0);
}
else
w83877tf->index = val;
@@ -178,25 +213,52 @@ static uint8_t w83877tf_read_3fx(uint16_t port, void *p)
return ret;
}
-void w83877tf_init()
+static void w83877_common_init(int chip, uint16_t base, uint8_t key)
{
memset(&w83877tf_global, 0, sizeof(w83877tf_t));
- io_sethandler(0x0250, 0x0003, w83877tf_read_25x, NULL, NULL, w83877tf_write_25x, NULL, NULL, &w83877tf_global);
-
+ if (base == 0x250)
+ io_sethandler(0x0250, 0x0003, w83877tf_read_25x, NULL, NULL, w83877tf_write_25x, NULL, NULL, &w83877tf_global);
+ else
+ io_sethandler(0x03f0, 0x0002, w83877tf_read_3fx, NULL, NULL, w83877tf_write_3fx, NULL, NULL, &w83877tf_global);
+
/*Defaults*/
w83877tf_global.regs[0x03] = 0x30;
w83877tf_global.regs[0x09] = 0x0c;
w83877tf_global.regs[0x0b] = 0x0c;
- w83877tf_global.regs[0x0c] = 0x28;
+ if (key == 0x88 || key == 0x86)
+ w83877tf_global.regs[0x0c] = 0x08;
+ else
+ w83877tf_global.regs[0x0c] = 0x28;
w83877tf_global.regs[0x0d] = 0xa3;
- w83877tf_global.regs[0x16] = 0x04;
- w83877tf_global.regs[0x20] = 0xfc;
- w83877tf_global.regs[0x23] = 0xde;
- w83877tf_global.regs[0x24] = 0xfe;
- w83877tf_global.regs[0x25] = 0xbe;
- w83877tf_global.regs[0x26] = 0x23;
- w83877tf_global.regs[0x27] = 0x05;
- w83877tf_global.regs[0x28] = 0x43;
- w83877tf_global.regs[0x29] = 0x60;
+ if (base == 0x250)
+ w83877tf_global.regs[0x16] = 0x04;
+ else
+ w83877tf_global.regs[0x16] = 0x05;
+ w83877tf_global.regs[0x20] = 0;
+ w83877tf_global.regs[0x23] = 0;
+ w83877tf_global.regs[0x24] = 0;
+ w83877tf_global.regs[0x25] = 0;
+ w83877tf_global.regs[0x26] = 0;
+ w83877tf_global.regs[0x27] = 0;
+ w83877tf_global.regs[0x28] = 0;
+ w83877tf_global.regs[0x29] = 0;
+
+ fdc_remove();
+ lpt1_remove();
+ lpt2_remove();
+ serial1_remove();
+ serial2_remove();
+
+ w83877tf_global.chip = chip;
+ w83877tf_global.unlock_key = key;
+}
+
+void w83877f_init(uint16_t base, uint8_t key)
+{
+ w83877_common_init(CHIP_W83877F, base, key);
+}
+void w83877tf_init(uint16_t base, uint8_t key)
+{
+ w83877_common_init(CHIP_W83877TF, base, key);
}
diff --git a/src/w83877tf.h b/src/w83877tf.h
index dcfb853..6371497 100644
--- a/src/w83877tf.h
+++ b/src/w83877tf.h
@@ -1 +1,2 @@
-void w83877tf_init();
+void w83877f_init(uint16_t base, uint8_t key);
+void w83877tf_init(uint16_t base, uint8_t key);
diff --git a/src/w83977tf.c b/src/w83977tf.c
new file mode 100644
index 0000000..520b4ed
--- /dev/null
+++ b/src/w83977tf.c
@@ -0,0 +1,197 @@
+#include "ibm.h"
+
+#include "fdc.h"
+#include "io.h"
+#include "lpt.h"
+#include "serial.h"
+#include "w83977tf.h"
+
+typedef struct winbond_t
+{
+ int cur_reg;
+ int cur_device;
+ int index;
+
+ uint8_t unlock_key;
+ uint8_t key[2];
+ int enable_regs;
+
+ struct
+ {
+ int enable;
+ uint16_t addr;
+ int irq;
+ int dma;
+ } dev[11];
+} winbond_t;
+
+static winbond_t winbond_global;
+
+#define DEV_FDC 0x0
+#define DEV_LPT 0x1
+#define DEV_COM1 0x2
+#define DEV_COM2 0x3
+#define DEV_KBC 0x5
+#define DEV_GPIO 0x7
+#define DEV_GPIO_II 0x8
+#define DEV_GPIO_III 0x9
+#define DEV_ACPI 0xa
+
+#define REG_DEVICE 0x07
+#define REG_DEVICE_ID 0x20
+#define REG_DEVICE_REV 0x21
+#define REG_ENABLE 0x30
+#define REG_ADDRHI 0x60
+#define REG_ADDRLO 0x61
+#define REG_IRQ 0x70
+#define REG_DMA 0x74
+
+void winbond_write_reg(winbond_t *winbond, int index, uint8_t val)
+{
+ if (index == REG_DEVICE)
+ winbond->cur_device = val & 0xf;
+ else
+ {
+// pclog("Write winbond %02x [%02x] %02x\n", winbond->cur_reg, winbond->cur_device, val);
+ switch (index)
+ {
+ case REG_ENABLE:
+ if (winbond->cur_device <= DEV_ACPI)
+ winbond->dev[winbond->cur_device].enable = val;
+ break;
+ case REG_ADDRLO:
+ if (winbond->cur_device <= DEV_ACPI)
+ winbond->dev[winbond->cur_device].addr = (winbond->dev[winbond->cur_device].addr & 0xff00) | val;
+ break;
+ case REG_ADDRHI:
+ if (winbond->cur_device <= DEV_ACPI)
+ winbond->dev[winbond->cur_device].addr = (winbond->dev[winbond->cur_device].addr & 0x00ff) | (val << 8);
+ break;
+ case REG_IRQ:
+ if (winbond->cur_device <= DEV_ACPI)
+ winbond->dev[winbond->cur_device].irq = val;
+ break;
+ case REG_DMA:
+ if (winbond->cur_device <= DEV_ACPI)
+ winbond->dev[winbond->cur_device].dma = val;
+ break;
+ }
+
+ switch (winbond->cur_device)
+ {
+ case DEV_FDC:
+ fdc_remove();
+ if (winbond->dev[DEV_FDC].enable & 1)
+ fdc_add();
+ break;
+ case DEV_COM1:
+ serial1_remove();
+ if (winbond->dev[DEV_COM1].enable & 1)
+ serial1_set(winbond->dev[DEV_COM1].addr, winbond->dev[DEV_COM1].irq);
+ break;
+ case DEV_COM2:
+ serial2_remove();
+ if (winbond->dev[DEV_COM2].enable & 1)
+ serial2_set(winbond->dev[DEV_COM2].addr, winbond->dev[DEV_COM2].irq);
+ break;
+ case DEV_LPT:
+ lpt1_remove();
+ lpt2_remove();
+ if (winbond->dev[DEV_LPT].enable & 1)
+ lpt1_init(winbond->dev[DEV_LPT].addr);
+ break;
+ }
+ }
+}
+
+uint8_t winbond_read_reg(winbond_t *winbond, int index)
+{
+// pclog("Read winbond %02x\n", winbond->cur_reg);
+
+ switch (index)
+ {
+ case REG_DEVICE:
+ return winbond->cur_device;
+ case REG_DEVICE_ID:
+ return 0x97;
+ case REG_DEVICE_REV:
+ return 0x73;
+ case REG_ENABLE:
+ return winbond->dev[winbond->cur_device].enable;
+ case REG_ADDRLO:
+ return winbond->dev[winbond->cur_device].addr & 0xff;
+ case REG_ADDRHI:
+ return winbond->dev[winbond->cur_device].addr >> 8;
+ case REG_IRQ:
+ return winbond->dev[winbond->cur_device].irq;
+ case REG_DMA:
+ return winbond->dev[winbond->cur_device].dma;
+ }
+
+ return 0xff;
+}
+
+static void winbond_write_3fx(uint16_t port, uint8_t val, void *p)
+{
+ winbond_t *winbond = (winbond_t *)p;
+
+// pclog("winbond_write: port=%04x val=%02x\n", port, val);
+
+ switch (port)
+ {
+ case 0x3f0: /*Enable/index register*/
+ if (val == 0xaa)
+ {
+ fdc_3f1_enable(1);
+ winbond->enable_regs = 0;
+ }
+ else if (!winbond->enable_regs)
+ {
+ winbond->key[1] = winbond->key[0];
+ winbond->key[0] = val;
+ winbond->enable_regs = (winbond->key[0] == winbond->unlock_key && winbond->key[1] == winbond->unlock_key);
+ /*The FDC conflicts with the 3fx config registers, so disable
+ it when enabling config registers*/
+ if (winbond->enable_regs)
+ fdc_3f1_enable(0);
+ }
+ else
+ winbond->index = val;
+ break;
+ case 0x3f1: /*Data*/
+ if (winbond->enable_regs)
+ winbond_write_reg(winbond, winbond->index, val);
+ break;
+ }
+}
+
+static uint8_t winbond_read_3fx(uint16_t port, void *p)
+{
+ winbond_t *winbond = (winbond_t *)p;
+ uint8_t ret = 0xff;
+
+ switch (port)
+ {
+ case 0x3f0: /*Index*/
+ if (winbond->enable_regs)
+ ret = winbond->index;
+ break;
+
+ case 0x3f1: /*Data*/
+ if (winbond->enable_regs)
+ ret = winbond_read_reg(winbond, winbond->index);
+ break;
+ }
+
+// pclog("winbond_read: port=%04x val=%02x\n", port, ret);
+
+ return ret;
+}
+
+void w83977tf_init(uint16_t base, uint8_t key)
+{
+ memset(&winbond_global, 0, sizeof(winbond_t));
+
+ winbond_global.unlock_key = key;
+ io_sethandler(base, 0x0002, winbond_read_3fx, NULL, NULL, winbond_write_3fx, NULL, NULL, &winbond_global);
+}
diff --git a/src/w83977tf.h b/src/w83977tf.h
new file mode 100644
index 0000000..290f571
--- /dev/null
+++ b/src/w83977tf.h
@@ -0,0 +1 @@
+void w83977tf_init(uint16_t base, uint8_t key);
diff --git a/src/wx-app.cc b/src/wx-app.cc
index ca70c16..cbe4f17 100644
--- a/src/wx-app.cc
+++ b/src/wx-app.cc
@@ -33,6 +33,7 @@ extern void InitXmlResource();
wxDEFINE_EVENT(WX_CALLBACK_EVENT, CallbackEvent);
wxDEFINE_EVENT(WX_EXIT_EVENT, wxCommandEvent);
wxDEFINE_EVENT(WX_STOP_EMULATION_EVENT, wxCommandEvent);
+wxDEFINE_EVENT(WX_STOP_EMULATION_NOW_EVENT, wxCommandEvent);
wxDEFINE_EVENT(WX_EXIT_COMPLETE_EVENT, wxCommandEvent);
wxDEFINE_EVENT(WX_SHOW_WINDOW_EVENT, wxCommandEvent);
wxDEFINE_EVENT(WX_POPUP_MENU_EVENT, PopupMenuEvent);
@@ -89,6 +90,7 @@ Frame::Frame(App* app, const wxString& title, const wxPoint& pos,
Bind(WX_EXIT_EVENT, &Frame::OnExitEvent, this);
Bind(WX_EXIT_COMPLETE_EVENT, &Frame::OnExitCompleteEvent, this);
Bind(WX_STOP_EMULATION_EVENT, &Frame::OnStopEmulationEvent, this);
+ Bind(WX_STOP_EMULATION_NOW_EVENT, &Frame::OnStopEmulationNowEvent, this);
Bind(WX_CALLBACK_EVENT, &Frame::OnCallbackEvent, this);
#ifdef _WIN32
Bind(WX_WIN_SEND_MESSAGE_EVENT, &Frame::OnWinSendMessageEvent, this);
@@ -151,6 +153,15 @@ void Frame::OnStopEmulationEvent(wxCommandEvent& event)
}
}
+void Frame::OnStopEmulationNowEvent(wxCommandEvent& event)
+{
+ stop_emulation();
+ if (!config_override)
+ ShowConfigSelection();
+ else
+ Quit(1);
+}
+
void Frame::OnShowWindowEvent(wxCommandEvent& event)
{
wxWindow* window = (wxWindow*)event.GetEventObject();
diff --git a/src/wx-app.h b/src/wx-app.h
index 803f5d1..4c6d29a 100644
--- a/src/wx-app.h
+++ b/src/wx-app.h
@@ -14,6 +14,7 @@ class PopupMenuEvent;
wxDECLARE_EVENT(WX_CALLBACK_EVENT, CallbackEvent);
wxDECLARE_EVENT(WX_EXIT_EVENT, wxCommandEvent);
wxDECLARE_EVENT(WX_STOP_EMULATION_EVENT, wxCommandEvent);
+wxDECLARE_EVENT(WX_STOP_EMULATION_NOW_EVENT, wxCommandEvent);
wxDECLARE_EVENT(WX_EXIT_COMPLETE_EVENT, wxCommandEvent);
wxDECLARE_EVENT(WX_SHOW_WINDOW_EVENT, wxCommandEvent);
wxDECLARE_EVENT(WX_POPUP_MENU_EVENT, PopupMenuEvent);
@@ -155,6 +156,7 @@ private:
void OnExitEvent(wxCommandEvent& event);
void OnExitCompleteEvent(wxCommandEvent& event);
void OnStopEmulationEvent(wxCommandEvent& event);
+ void OnStopEmulationNowEvent(wxCommandEvent& event);
void OnShowWindowEvent(wxCommandEvent& event);
void OnPopupMenuEvent(PopupMenuEvent& event);
void OnCallbackEvent(CallbackEvent& event);
diff --git a/src/wx-config.c b/src/wx-config.c
index 90c38a3..9bc5c8d 100644
--- a/src/wx-config.c
+++ b/src/wx-config.c
@@ -20,6 +20,8 @@
#include "video.h"
#include "vid_voodoo.h"
+#include "minivhd/minivhd.h"
+
//#define MAX_CYLINDERS ((((1 << 28)-1) / 16) / 63)
#define MAX_CYLINDERS 265264 /*Award 430VX won't POST with a larger drive*/
extern int pause;
@@ -46,10 +48,14 @@ static int new_zip_channel;
extern int pause;
+static int memspin_old;
+
extern void deviceconfig_open(void* hwnd, device_t *device);
extern int hdconf_init(void* hdlg);
extern int hdconf_update(void* hdlg);
+static int hdd_controller_selected_is_ide(void* hdlg);
+static int hdd_controller_selected_is_scsi(void* hdlg);
static int hdd_controller_selected_has_config(void *hdlg);
static device_t *hdd_controller_selected_get_device(void *hdlg);
@@ -76,23 +82,51 @@ static int mouse_valid(int type, int model)
return FALSE;
}*/
+static void recalc_fpu_list(void *hdlg, int model, int manu, int cpu, int fpu)
+{
+ void *h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOFPU"));
+ int c = 0;
+
+ wx_sendmessage(h, WX_CB_RESETCONTENT, 0, 0);
+ wx_sendmessage(h, WX_CB_SETCURSEL, 0, 0);
+
+ while (1)
+ {
+ const char *name = fpu_get_name_from_index(model, manu, cpu, c);
+ int type = fpu_get_type_from_index(model, manu, cpu, c);
+ if (!name)
+ break;
+
+ wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)name);
+ if (!c || type == fpu)
+ wx_sendmessage(h, WX_CB_SETCURSEL, c, 0);
+
+ c++;
+ }
+ if (c > 1)
+ wx_enablewindow(h, TRUE);
+ else
+ wx_enablewindow(h, FALSE);
+}
+
static void recalc_vid_list(void* hdlg, int model, int force_builtin_video)
{
void* h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOVID"));
int c = 0, d = 0;
int found_card = 0;
int cur_gfxcard = gfxcard;
+ int romset = model_getromset_from_model(model);
wx_sendmessage(h, WX_CB_RESETCONTENT, 0, 0);
wx_sendmessage(h, WX_CB_SETCURSEL, 0, 0);
-
+
if (model_has_fixed_gfx(model))
{
wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)"Built-in video");
wx_sendmessage(h, WX_CB_SETCURSEL, 0, 0);
wx_enablewindow(h, FALSE);
h = wx_getdlgitem(hdlg, WX_ID("IDC_CONFIGUREVID"));
- wx_enablewindow(h, FALSE);
+ wx_enablewindow(h, video_card_has_config(gfxcard, romset));
return;
}
@@ -107,7 +141,10 @@ static void recalc_vid_list(void* hdlg, int model, int force_builtin_video)
}
d++;
}
-
+
+ if (cur_gfxcard == GFX_BUILTIN && !model_has_fixed_gfx(model) && !model_has_optional_gfx(model))
+ cur_gfxcard = 0;
+
while (1)
{
char *s = video_card_getname(c);
@@ -116,7 +153,10 @@ static void recalc_vid_list(void* hdlg, int model, int force_builtin_video)
break;
if (video_card_available(c) && gfx_present[video_new_to_old(c)] &&
- ((models[model].flags & MODEL_PCI) || !(video_card_getdevice(c)->flags & DEVICE_PCI)))
+ ((models[model].flags & MODEL_PCI) || !(video_card_getdevice(c, romset)->flags & DEVICE_PCI)) &&
+ ((models[model].flags & MODEL_MCA) || !(video_card_getdevice(c, romset)->flags & DEVICE_MCA)) &&
+ (!(models[model].flags & MODEL_MCA) || (video_card_getdevice(c, romset)->flags & DEVICE_MCA))
+ )
{
wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)s);
if (video_new_to_old(c) == gfxcard && !found_card)
@@ -135,7 +175,7 @@ static void recalc_vid_list(void* hdlg, int model, int force_builtin_video)
wx_enablewindow(h, TRUE);
h = wx_getdlgitem(hdlg, WX_ID("IDC_CONFIGUREVID"));
- if (video_card_has_config(video_old_to_new(cur_gfxcard)))
+ if (video_card_has_config(video_old_to_new(cur_gfxcard), romset))
wx_enablewindow(h, TRUE);
else
wx_enablewindow(h, FALSE);
@@ -259,7 +299,7 @@ static void recalc_hdd_list(void* hdlg, int model, int use_selected_hdd, int for
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOHDD"));
hdd_type = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
h = wx_getdlgitem(hdlg, WX_ID("IDC_HDCBOOK"));
-
+
while (wx_sendmessage(h, WX_CHB_GETPAGECOUNT, 0, 0))
wx_sendmessage(h, WX_CHB_REMOVEPAGE, 0, 0);
@@ -267,20 +307,20 @@ static void recalc_hdd_list(void* hdlg, int model, int use_selected_hdd, int for
{
void *page;
char s[80];
-
+
sprintf(s, "IDC_HDPANEL[%i]", c);
-
+
page = wx_getdlgitem(hdlg, WX_ID(s));
wx_sendmessage(page, WX_REPARENT, (LONG_PARAM)h, 0);
wx_sendmessage(h, WX_CHB_ADDPAGE, (LONG_PARAM)page, (LONG_PARAM)"dummy name");
- }
+ }
if (hdd_controller_is_scsi(hdd_names[hdd_type]))
- {
+ {
for (c = 0; c < 7; c++)
{
void *page;
char s[80];
-
+
sprintf(s, "IDC_HDPANEL[%i]", c);
page = wx_getdlgitem(hdlg, WX_ID(s));
wx_sendmessage(page, WX_REPARENT, (LONG_PARAM)h, 0);
@@ -312,7 +352,7 @@ static void recalc_hdd_list(void* hdlg, int model, int use_selected_hdd, int for
{
void *page;
char s[80];
-
+
sprintf(s, "IDC_HDPANEL[%i]", c);
page = wx_getdlgitem(hdlg, WX_ID(s));
wx_sendmessage(page, WX_REPARENT, (LONG_PARAM)h, 0);
@@ -326,28 +366,85 @@ static void recalc_hdd_list(void* hdlg, int model, int use_selected_hdd, int for
}
}
-static void recalc_cd_list(void *hdlg, int cur_speed)
+// TODO: split this into model/speed recalcs?
+static void recalc_cd_list(void *hdlg, int cur_speed, char *cur_model)
{
- void *h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDSPEED"));
+ int temp_model = -1;
+ void *h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDMODEL"));
int c = 0;
-
+ int found = 0;
+
wx_sendmessage(h, WX_CB_RESETCONTENT, 0, 0);
+ if (hdd_controller_selected_is_ide(hdlg) || hdd_controller_selected_is_scsi(hdlg))
+ wx_enablewindow(h, TRUE);
+ else
+ wx_enablewindow(h, FALSE);
+ while (1)
+ {
+ char s[40];
+ char *model;
+
+ if ((cd_get_model_interfaces(c) == CD_MODEL_INTERFACE_ALL) ||
+ (cd_get_model_interfaces(c) == CD_MODEL_INTERFACE_IDE && hdd_controller_selected_is_ide(hdlg)) ||
+ (cd_get_model_interfaces(c) == CD_MODEL_INTERFACE_SCSI && hdd_controller_selected_is_scsi(hdlg)))
+ {
+
+ model = cd_get_model(c);
+ sprintf(s, "%s", model);
+ wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)s);
+
+ if (!strncmp(s, cur_model, 40))
+ {
+ wx_sendmessage(h, WX_CB_SETCURSEL, c, 0);
+ temp_model = c;
+ found = 1;
+ }
+ }
+
+ c++;
+ if (c > MAX_CD_MODEL)
+ break;
+ }
+ if (!found)
+ wx_sendmessage(h, WX_CB_SETCURSEL, 0, 0); // assume that there is always at least one TODO: is this necessary?
+
+
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDSPEED"));
+ c = 0;
+ found = 0;
+
+ wx_sendmessage(h, WX_CB_RESETCONTENT, 0, 0);
+ if (temp_model >= 0 && cd_get_model_speed(temp_model) != -1)
+ {
+ // this model has a specific speed
+ wx_enablewindow(h, FALSE);
+ cur_speed = cd_get_model_speed(temp_model);
+ }
+ else if (hdd_controller_selected_is_ide(hdlg) || hdd_controller_selected_is_scsi(hdlg))
+ wx_enablewindow(h, TRUE);
+ else
+ wx_enablewindow(h, FALSE);
while (1)
{
char s[8];
int speed;
-
+
speed = cd_get_speed(c);
sprintf(s, "%iX", speed);
wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)s);
-
+
if (speed == cur_speed)
+ {
wx_sendmessage(h, WX_CB_SETCURSEL, c, 0);
-
+ found = 1;
+ }
+
c++;
if (speed >= MAX_CD_SPEED)
break;
}
+ if (!found)
+ wx_sendmessage(h, WX_CB_SETCURSEL, 0, 0); // fall back TODO: is this necessary?
}
#ifdef USE_NETWORKING
@@ -401,8 +498,8 @@ int config_dlgsave(void* hdlg)
char temp_str[256];
void* h;
int c;
- int gfx, fpu;
- int temp_cpu, temp_cpu_m, temp_model;
+ int gfx;//, fpu;
+ int temp_cpu, temp_cpu_m, temp_model, temp_fpu;
int temp_GAMEBLASTER, temp_GUS, temp_SSI2001, temp_voodoo, temp_sound_card_current;
int temp_dynarec;
int temp_fda_type, temp_fdb_type;
@@ -438,8 +535,11 @@ int config_dlgsave(void* hdlg)
temp_cpu_m = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO3"));
temp_cpu = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
- fpu = (models[temp_model].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type
- >= CPU_i486DX) ? 1 : 0;
+// fpu = (models[temp_model].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type
+// >= CPU_i486DX) ? 1 : 0;
+
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOFPU"));
+ temp_fpu = fpu_get_type_from_index(temp_model, temp_cpu_m, temp_cpu, wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0));
h = wx_getdlgitem(hdlg, WX_ID("IDC_CHECK3"));
temp_GAMEBLASTER = wx_sendmessage(h, WX_BM_GETCHECK, 0, 0);
@@ -469,7 +569,7 @@ int config_dlgsave(void* hdlg)
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOJOY"));
temp_joystick_type = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
-
+
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOMOUSE"));
temp_mouse_type = settings_list_to_mouse[wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0)];
@@ -484,10 +584,10 @@ int config_dlgsave(void* hdlg)
#ifdef USE_NETWORKING
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_NETCARD"));
temp_network_card = settings_list_to_network[wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0)];
-#endif
+#endif
- if (temp_model != model || gfx != gfxcard || mem != mem_size ||
- fpu != hasfpu || temp_GAMEBLASTER != GAMEBLASTER || temp_GUS != GUS ||
+ if (temp_model != model || gfx != gfxcard || mem != mem_size || temp_fpu != fpu_type ||
+ temp_GAMEBLASTER != GAMEBLASTER || temp_GUS != GUS ||
temp_SSI2001 != SSI2001 || temp_sound_card_current != sound_card_current ||
temp_voodoo != voodoo_enabled || temp_dynarec != cpu_use_dynarec ||
temp_fda_type != fdd_get_type(0) || temp_fdb_type != fdd_get_type(1) ||
@@ -507,6 +607,7 @@ int config_dlgsave(void* hdlg)
mem_size = mem;
cpu_manufacturer = temp_cpu_m;
cpu = temp_cpu;
+ fpu_type = temp_fpu;
GAMEBLASTER = temp_GAMEBLASTER;
GUS = temp_GUS;
SSI2001 = temp_SSI2001;
@@ -577,6 +678,10 @@ int config_dlgsave(void* hdlg)
cd_speed = cd_get_speed(wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0));
cd_set_speed(cd_speed);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDMODEL"));
+ cd_model = cd_get_model(wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0));
+ cd_set_model(cd_model);
+
if (has_been_inited)
saveconfig(NULL);
@@ -596,11 +701,12 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
void* h;
int c, d;
int gfx, mem;
- int temp_cpu, temp_cpu_m, temp_model;
+ int temp_cpu, temp_cpu_m, temp_model, temp_fpu;
int temp_sound_card_current;
int temp_dynarec;
int cpu_flags;
int cpu_type;
+ int temp_cd_model, temp_cd_speed;
int temp_mouse_type;
#ifdef USE_NETWORKING
int temp_network_card;
@@ -631,6 +737,8 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
c++;
}
wx_sendmessage(h, WX_CB_SETCURSEL, modeltolist[model], 0);
+ model = listtomodel[modeltolist[model]];
+ romset = model_getromset();
prev_model = model;
recalc_vid_list(hdlg, romstomodel[romset], 0);
@@ -661,6 +769,8 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
wx_enablewindow(h, TRUE);
wx_sendmessage(h, WX_CB_SETCURSEL, cpu, 0);
+ recalc_fpu_list(hdlg, romstomodel[romset], cpu_manufacturer, cpu, fpu_type);
+
recalc_snd_list(hdlg, romstomodel[romset]);
h = wx_getdlgitem(hdlg, WX_ID("IDC_CHECK3"));
@@ -706,9 +816,15 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
| models[romstomodel[romset]].max_ram);
wx_sendmessage(h, WX_UDM_SETINCR, 0, models[model].ram_granularity);
if (!((models[model].flags & MODEL_AT) && models[model].ram_granularity < 128))
+ {
wx_sendmessage(h, WX_UDM_SETPOS, 0, mem_size);
+ memspin_old = mem_size;
+ }
else
+ {
wx_sendmessage(h, WX_UDM_SETPOS, 0, mem_size / 1024);
+ memspin_old = mem_size / 1024;
+ }
h = wx_getdlgitem(hdlg, WX_ID("IDC_CONFIGUREMOD"));
if (model_getdevice(model))
@@ -833,13 +949,13 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
hd_changed = 0;
new_cdrom_channel = cdrom_channel;
new_zip_channel = zip_channel;
-
+
hdconf_init(hdlg);
-
+
for (c = 0; c < 7; c++)
{
char s[80];
-
+
sprintf(s, "IDC_COMBODRIVETYPE[%i]", c);
h = wx_getdlgitem(hdlg, WX_ID(s));
wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)"Hard drive");
@@ -852,8 +968,8 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
else
wx_sendmessage(h, WX_CB_SETCURSEL, 0, 0);
}
-
- recalc_cd_list(hdlg, cd_speed);
+
+ recalc_cd_list(hdlg, cd_speed, cd_model);
#ifdef USE_NETWORKING
recalc_net_list(hdlg, romstomodel[romset]);
@@ -872,15 +988,15 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
{
if (wParam == WX_ID("IDC_COMBO1"))
{
- int force_ide = 0;
+ int force_ide = 0;
int force_builtin_video = 0;
-
+
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO1"));
temp_model = listtomodel[wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0)];
-
+
if (temp_model == prev_model)
break;
-
+
if ((models[temp_model].flags & MODEL_HAS_IDE) && !(models[prev_model].flags & MODEL_HAS_IDE))
force_ide = 1;
if (model_has_optional_gfx(temp_model))
@@ -922,6 +1038,10 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
temp_cpu = c - 1;
wx_sendmessage(h, WX_CB_SETCURSEL, temp_cpu, 0);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOFPU"));
+ temp_fpu = fpu_get_type_from_index(temp_model, temp_cpu_m, temp_cpu, wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0));
+ recalc_fpu_list(hdlg, temp_model, temp_cpu_m, temp_cpu, temp_fpu);
+
h = wx_getdlgitem(hdlg, WX_ID("IDC_CHECKDYNAREC"));
temp_dynarec = wx_sendmessage(h, WX_BM_GETCHECK, 0, 0);
@@ -1004,6 +1124,12 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
recalc_hdd_list(hdlg, temp_model, 1, force_ide);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDMODEL"));
+ temp_cd_model = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDSPEED"));
+ temp_cd_speed = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
+ recalc_cd_list(hdlg, cd_get_speed(temp_cd_speed), cd_get_model(temp_cd_model));
+
recalc_snd_list(hdlg, temp_model);
#ifdef USE_NETWORKING
recalc_net_list(hdlg, temp_model);
@@ -1031,6 +1157,10 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
temp_cpu = c - 1;
wx_sendmessage(h, WX_CB_SETCURSEL, temp_cpu, 0);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOFPU"));
+ temp_fpu = fpu_get_type_from_index(temp_model, temp_cpu_m, temp_cpu, wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0));
+ recalc_fpu_list(hdlg, temp_model, temp_cpu_m, temp_cpu, temp_fpu);
+
h = wx_getdlgitem(hdlg, WX_ID("IDC_CHECKDYNAREC"));
temp_dynarec = wx_sendmessage(h, WX_BM_GETCHECK, 0, 0);
@@ -1063,6 +1193,10 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO3"));
temp_cpu = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOFPU"));
+ temp_fpu = fpu_get_type_from_index(temp_model, temp_cpu_m, temp_cpu, wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0));
+ recalc_fpu_list(hdlg, temp_model, temp_cpu_m, temp_cpu, temp_fpu);
+
h = wx_getdlgitem(hdlg, WX_ID("IDC_CHECKDYNAREC"));
temp_dynarec = wx_sendmessage(h, WX_BM_GETCHECK, 0, 0);
@@ -1095,11 +1229,11 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
else if (wParam == WX_ID("IDC_CONFIGUREVID"))
{
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOVID"));
- wx_sendmessage(h, WX_CB_GETLBTEXT, wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0),
- (LONG_PARAM) temp_str);
+ wx_sendmessage(h, WX_CB_GETLBTEXT, wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0), (LONG_PARAM) temp_str);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO1"));
+ temp_model = listtomodel[wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0)];
- deviceconfig_open(hdlg,
- (void *) video_card_getdevice(video_card_getid(temp_str)));
+ deviceconfig_open(hdlg, (void *)video_card_getdevice(video_card_getid(temp_str), model_getromset_from_model(temp_model)));
}
else if (wParam == WX_ID("IDC_COMBOVID"))
{
@@ -1112,7 +1246,7 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
gfx = video_card_getid(temp_str);
h = wx_getdlgitem(hdlg, WX_ID("IDC_CONFIGUREVID"));
- if (video_card_has_config(gfx) && !model_has_fixed_gfx(temp_model))
+ if (video_card_has_config(gfx, model_getromset_from_model(temp_model)))
wx_enablewindow(h, TRUE);
else
wx_enablewindow(h, FALSE);
@@ -1146,17 +1280,31 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO1"));
temp_model = listtomodel[wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0)];
recalc_hdd_list(hdlg, temp_model, 1, 0);
+
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDMODEL"));
+ temp_cd_model = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDSPEED"));
+ temp_cd_speed = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
+ recalc_cd_list(hdlg, cd_get_speed(temp_cd_speed), cd_get_model(temp_cd_model));
}
else if (wParam == WX_ID("IDC_CONFIGUREHDD"))
{
deviceconfig_open(hdlg, (void *)hdd_controller_selected_get_device(hdlg));
}
+ else if (wParam == WX_ID("IDC_COMBO_CDMODEL"))
+ {
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDMODEL"));
+ temp_cd_model = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_CDSPEED"));
+ temp_cd_speed = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
+ recalc_cd_list(hdlg, cd_get_speed(temp_cd_speed), cd_get_model(temp_cd_model));
+ }
#ifdef USE_NETWORKING
else if (wParam == WX_ID("IDC_COMBO_NETCARD"))
{
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_NETCARD"));
temp_network_card = settings_list_to_network[wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0)];
-
+
h = wx_getdlgitem(hdlg, WX_ID("IDC_CONFIGURE_NETCARD"));
if (network_card_has_config(temp_network_card))
wx_enablewindow(h, TRUE);
@@ -1167,14 +1315,14 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
{
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO_NETCARD"));
temp_network_card = settings_list_to_network[wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0)];
-
+
deviceconfig_open(hdlg, (void *)network_card_getdevice(temp_network_card));
}
#endif
else if (wParam == WX_ID("IDC_COMBOJOY"))
{
int temp_joystick_type;
-
+
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOJOY"));
temp_joystick_type = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
@@ -1190,7 +1338,7 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
else if (wParam == WX_ID("IDC_JOY1"))
{
int temp_joystick_type;
-
+
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOJOY"));
temp_joystick_type = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
joystickconfig_open(hdlg, 0, temp_joystick_type);
@@ -1198,7 +1346,7 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
else if (wParam == WX_ID("IDC_JOY2"))
{
int temp_joystick_type;
-
+
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOJOY"));
temp_joystick_type = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
joystickconfig_open(hdlg, 1, temp_joystick_type);
@@ -1206,7 +1354,7 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
else if (wParam == WX_ID("IDC_JOY3"))
{
int temp_joystick_type;
-
+
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOJOY"));
temp_joystick_type = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
joystickconfig_open(hdlg, 2, temp_joystick_type);
@@ -1214,7 +1362,7 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
else if (wParam == WX_ID("IDC_JOY4"))
{
int temp_joystick_type;
-
+
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOJOY"));
temp_joystick_type = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
joystickconfig_open(hdlg, 3, temp_joystick_type);
@@ -1226,7 +1374,7 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
int mem;
int granularity;
int granularity_mask;
-
+
h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBO1"));
temp_model = listtomodel[wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0)];
@@ -1235,20 +1383,18 @@ int config_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
h = wx_getdlgitem(hdlg, WX_ID("IDC_MEMSPIN"));
mem = wx_sendmessage(h, WX_UDM_GETPOS, 0, 0);
- if (mem & granularity_mask)
+ if (mem < memspin_old)
{
- if ((mem & granularity_mask) < (granularity / 2))
- {
- /*Assume increase*/
- mem = (mem + granularity_mask) & ~granularity_mask;
- }
- else
- {
- /*Assumg decrease*/
- mem &= ~granularity_mask;
- }
- mem = wx_sendmessage(h, WX_UDM_SETPOS, 0, mem);
+ /*Assume decrease*/
+ mem &= ~granularity_mask;
}
+ else
+ {
+ /*Assume increase*/
+ mem = (mem + granularity_mask) & ~granularity_mask;
+ }
+ wx_sendmessage(h, WX_UDM_SETPOS, 0, mem);
+ memspin_old = mem;
}
#endif
return 0;
@@ -1285,6 +1431,22 @@ static int hdd_controller_selected_is_mfm(void* hdlg)
return hdd_controller_is_mfm(hdd_names[c]);
return 0;
}
+static int hdd_controller_selected_is_ide(void* hdlg)
+{
+ void* h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOHDD"));
+ int c = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
+ if (hdd_names[c])
+ return hdd_controller_is_ide(hdd_names[c]);
+ return 0;
+}
+static int hdd_controller_selected_is_scsi(void* hdlg)
+{
+ void* h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOHDD"));
+ int c = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
+ if (hdd_names[c])
+ return hdd_controller_is_scsi(hdd_names[c]);
+ return 0;
+}
static int hdd_controller_selected_has_config(void* hdlg)
{
void* h = wx_getdlgitem(hdlg, WX_ID("IDC_COMBOHDD"));
@@ -1400,7 +1562,7 @@ static void update_hdd_cdrom(void* hdlg)
}
static volatile int create_drive_pos;
-static int create_drive(void* data)
+static int create_drive_raw(void* data)
{
int c;
uint8_t buf[512];
@@ -1417,6 +1579,134 @@ static int create_drive(void* data)
return 1;
}
+static void vhd_progress_callback(uint32_t current_sector, uint32_t total_sectors)
+{
+ create_drive_pos = (int)current_sector;
+}
+
+/* If the disk geometry requested in the PCem GUI is not compatible with the internal VHD geometry,
+ * we adjust it to the next-largest size that is compatible. On average, this will be a difference
+ * of about 21 MB, and should only be necessary for VHDs larger than 31.5 GB, so should never be more
+ * than a tenth of a percent change in size.
+ */
+static void adjust_pcem_geometry_for_vhd(MVHDGeom *vhd_geometry)
+{
+ if (hd_new_cyl <= 65535)
+ return;
+
+ int desired_sectors = hd_new_cyl * hd_new_hpc * hd_new_spt;
+ if (desired_sectors > 267321600)
+ desired_sectors = 267321600;
+
+ int remainder = desired_sectors % 85680; /* 8560 is the LCM of 1008 (63*16) and 4080 (255*16) */
+ if (remainder > 0)
+ desired_sectors += (85680 - remainder);
+
+ hd_new_cyl = desired_sectors / (16 * 63);
+ hd_new_hpc = 16;
+ hd_new_spt = 63;
+
+ vhd_geometry->cyl = desired_sectors / (16 * 255);
+ vhd_geometry->heads = 16;
+ vhd_geometry->spt = 255;
+}
+
+static void adjust_vhd_geometry_for_pcem()
+{
+ if (hd_new_spt <= 63)
+ return;
+
+ int desired_sectors = hd_new_cyl * hd_new_hpc * hd_new_spt;
+ if (desired_sectors > 267321600)
+ desired_sectors = 267321600;
+
+ int remainder = desired_sectors % 85680; /* 8560 is the LCM of 1008 (63*16) and 4080 (255*16) */
+ if (remainder > 0)
+ desired_sectors -= remainder;
+
+ hd_new_cyl = desired_sectors / (16 * 63);
+ hd_new_hpc = 16;
+ hd_new_spt = 63;
+}
+
+static int create_drive_vhd_fixed(void *data)
+{
+ MVHDGeom geometry = { .cyl = hd_new_cyl, .heads = hd_new_hpc, .spt = hd_new_spt };
+ adjust_pcem_geometry_for_vhd(&geometry);
+
+ int vhd_error = 0;
+ MVHDMeta *vhd = mvhd_create_fixed(hd_new_name, geometry, &vhd_error, vhd_progress_callback);
+ if (vhd == NULL)
+ {
+ return 0;
+ }
+ else
+ {
+ mvhd_close(vhd);
+ return 1;
+ }
+}
+
+static int create_drive_vhd_dynamic(int blocksize)
+{
+ MVHDGeom geometry = { .cyl = hd_new_cyl, .heads = hd_new_hpc, .spt = hd_new_spt };
+ adjust_pcem_geometry_for_vhd(&geometry);
+ int vhd_error = 0;
+ MVHDCreationOptions options;
+ options.block_size_in_sectors = blocksize;
+ options.path = hd_new_name;
+ options.size_in_bytes = 0;
+ options.geometry = geometry;
+ options.type = MVHD_TYPE_DYNAMIC;
+
+ MVHDMeta *vhd = mvhd_create_ex(options, &vhd_error);
+ if (vhd == NULL)
+ {
+ return 0;
+ }
+ else
+ {
+ mvhd_close(vhd);
+ return 1;
+ }
+}
+
+static int create_drive_vhd_diff(char* parent_filename, int blocksize)
+{
+ int vhd_error = 0;
+ MVHDCreationOptions options;
+ options.block_size_in_sectors = blocksize;
+ options.path = hd_new_name;
+ options.parent_path = parent_filename;
+ options.type = MVHD_TYPE_DIFF;
+
+ MVHDMeta *vhd = mvhd_create_ex(options, &vhd_error);
+ if (vhd == NULL)
+ {
+ return 0;
+ }
+ else
+ {
+ MVHDGeom vhd_geom = mvhd_get_geometry(vhd);
+
+ if (vhd_geom.spt > 63)
+ {
+ hd_new_cyl = mvhd_calc_size_sectors(&vhd_geom) / (16 * 63);
+ hd_new_hpc = 16;
+ hd_new_spt = 63;
+ }
+ else
+ {
+ hd_new_cyl = vhd_geom.cyl;
+ hd_new_hpc = vhd_geom.heads;
+ hd_new_spt = vhd_geom.spt;
+ }
+
+ mvhd_close(vhd);
+ return 1;
+ }
+}
+
static int hdnew_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM lParam)
{
char s[260];
@@ -1424,7 +1714,7 @@ static int hdnew_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM l
int c;
PcemHDC hd[7];
FILE *f;
- int hd_type;
+ int hd_type, hd_format, hd_blocksize;
int size;
switch (message)
@@ -1457,6 +1747,22 @@ static int hdnew_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM l
}
wx_sendmessage(h, WX_CB_SETCURSEL, 0, 0);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_HDFORMAT"));
+ wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)"Raw (.img)");
+ wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)"Fixed-size VHD (.vhd)");
+ wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)"Dynamic-size VHD (.vhd)");
+ wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)"Differencing VHD (.vhd)");
+ wx_sendmessage(h, WX_CB_SETCURSEL, 0, 0);
+
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_HDBLOCKSIZE"));
+ wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)"Large blocks (2 MB)");
+ wx_sendmessage(h, WX_CB_ADDSTRING, 0, (LONG_PARAM)"Small blocks (512 KB)");
+ wx_sendmessage(h, WX_CB_SETCURSEL, 0, 0);
+ wx_sendmessage(h, WX_WM_SHOW, 0, (LONG_PARAM)0);
+
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_HDBLOCKSIZELABEL"));
+ wx_sendmessage(h, WX_WM_SETTEXT, 0, (LONG_PARAM)" ");
+
return TRUE;
case WX_COMMAND:
if (wParam == wxID_OK) {
@@ -1495,15 +1801,55 @@ static int hdnew_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM l
return TRUE;
}
- f = fopen64(hd_new_name, "wb");
- if (!f)
- {
- wx_messagebox(hdlg, "Can't open file for write", "PCem error", WX_MB_OK);
- return TRUE;
- }
- wx_progressdialog(hdlg, "PCem", "Creating drive, please wait...", create_drive, f, hd_new_cyl * hd_new_hpc * hd_new_spt, &create_drive_pos);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_HDFORMAT"));
+ hd_format = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
- wx_messagebox(hdlg, "Drive created, remember to partition and format the new drive.", "PCem", WX_MB_OK);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_HDBLOCKSIZE"));
+ hd_blocksize = (wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0) == 0) ? MVHD_BLOCK_LARGE : MVHD_BLOCK_SMALL;
+
+ if (hd_format == 0) /* Raw .img */
+ {
+ f = fopen64(hd_new_name, "wb");
+ if (!f)
+ {
+ wx_messagebox(hdlg, "Can't open file for write", "PCem error", WX_MB_OK);
+ return TRUE;
+ }
+ wx_progressdialog(hdlg, "PCem", "Creating drive, please wait...", create_drive_raw, f, hd_new_cyl * hd_new_hpc * hd_new_spt, &create_drive_pos);
+ }
+ else if (hd_format == 1) /* Fixed VHD */
+ {
+ if (!wx_progressdialog(hdlg, "PCem", "Creating drive, please wait...", create_drive_vhd_fixed, NULL, hd_new_cyl * hd_new_hpc * hd_new_spt, &create_drive_pos))
+ {
+ wx_messagebox(hdlg, "Can't create VHD", "PCem error", WX_MB_OK);
+ return TRUE;
+ }
+ }
+ else if (hd_format == 2) /* Dynamic VHD */
+ {
+ if (!create_drive_vhd_dynamic(hd_blocksize))
+ {
+ wx_messagebox(hdlg, "Can't create VHD", "PCem error", WX_MB_OK);
+ return TRUE;
+ }
+ }
+ else if (hd_format == 3) /* Differencing VHD */
+ {
+ if (!getfilewithcaption(hdlg, "VHD file (*.vhd)|*.vhd|All files (*.*)|*.*", "", "Select the parent VHD"))
+ {
+ if (!create_drive_vhd_diff(openfilestring, hd_blocksize))
+ {
+ wx_messagebox(hdlg, "Can't create VHD", "PCem error", WX_MB_OK);
+ return TRUE;
+ }
+ }
+ wx_messagebox(hdlg, "Differencing VHD image created.\n\n"
+ "WARNING: Do not open or modify the parent image(s) while this file exists.", "PCem", WX_MB_OK);
+ }
+ if (hd_format != 3)
+ {
+ wx_messagebox(hdlg, "Drive created, remember to partition and format the new drive.", "PCem", WX_MB_OK);
+ }
wx_enddialog(hdlg, 1);
return TRUE;
@@ -1511,7 +1857,13 @@ static int hdnew_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM l
wx_enddialog(hdlg, 0);
return TRUE;
} else if (ID_IS("IDC_CFILE")) {
- if (!getsfile(hdlg, "Hard disc image (*.img)|*.img|All files (*.*)|*.*", "", NULL, "img"))
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_HDFORMAT"));
+ hd_format = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
+ if (!getsfile(hdlg,
+ hd_format == 0 ? "Raw Hard disc image (*.img)|*.img|All files (*.*)|*.*" : "VHD file (*.vhd)|*.vhd|All files (*.*)|*.*",
+ "",
+ NULL,
+ hd_format == 0 ? "img" : "vhd"))
{
h = wx_getdlgitem(hdlg, WX_ID("IDC_EDITC"));
wx_sendmessage(h, WX_WM_SETTEXT, 0, (LONG_PARAM) openfilestring);
@@ -1591,6 +1943,68 @@ static int hdnew_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM l
}
return TRUE;
}
+ else if (ID_IS("IDC_HDFORMAT")) {
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_HDFORMAT"));
+ hd_format = wx_sendmessage(h, WX_CB_GETCURSEL, 0, 0);
+ if (hd_format == 3) /* They switched to a dynamic VHD; disable the geometry fields. */
+ {
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_EDIT1"));
+ wx_sendmessage(h, WX_WM_SETTEXT, 0, (LONG_PARAM)"(use parent)");
+ wx_sendmessage(h, WX_WM_ENABLE, 0, (LONG_PARAM)0);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_EDIT2"));
+ wx_sendmessage(h, WX_WM_SETTEXT, 0, (LONG_PARAM)"(use parent)");
+ wx_sendmessage(h, WX_WM_ENABLE, 0, (LONG_PARAM)0);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_EDIT3"));
+ wx_sendmessage(h, WX_WM_SETTEXT, 0, (LONG_PARAM)"(use parent)");
+ wx_sendmessage(h, WX_WM_ENABLE, 0, (LONG_PARAM)0);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_EDIT4"));
+ wx_sendmessage(h, WX_WM_SETTEXT, 0, (LONG_PARAM)"(use parent)");
+ wx_sendmessage(h, WX_WM_ENABLE, 0, (LONG_PARAM)0);
+
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_HDTYPE"));
+ wx_sendmessage(h, WX_CB_SETCURSEL, 0, 0);
+ wx_sendmessage(h, WX_WM_ENABLE, 0, (LONG_PARAM)0);
+ }
+ else /* Restore geometry fields if necessary. */
+ {
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_EDIT1"));
+ wx_sendmessage(h, WX_WM_GETTEXT, 0, (LONG_PARAM)s);
+ if (!strncmp(s, "(use parent)", 12))
+ {
+ wx_sendmessage(h, WX_WM_SETTEXT, 0, (LONG_PARAM)"63");
+ wx_sendmessage(h, WX_WM_ENABLE, 0, (LONG_PARAM)1);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_EDIT2"));
+ wx_sendmessage(h, WX_WM_SETTEXT, 0, (LONG_PARAM)"16");
+ wx_sendmessage(h, WX_WM_ENABLE, 0, (LONG_PARAM)1);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_EDIT3"));
+ wx_sendmessage(h, WX_WM_SETTEXT, 0, (LONG_PARAM)"511");
+ wx_sendmessage(h, WX_WM_ENABLE, 0, (LONG_PARAM)1);
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_EDIT4"));
+ wx_sendmessage(h, WX_WM_SETTEXT, 0, (LONG_PARAM)"251");
+ wx_sendmessage(h, WX_WM_ENABLE, 0, (LONG_PARAM)1);
+
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_HDTYPE"));
+ wx_sendmessage(h, WX_WM_ENABLE, 0, (LONG_PARAM)1);
+ }
+ }
+
+ if (hd_format == 2 || hd_format == 3) /* For dynamic and diff VHDs, show the block size dropdown. */
+ {
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_HDBLOCKSIZELABEL"));
+ wx_sendmessage(h, WX_WM_SETTEXT, 0, (LONG_PARAM)"Block size:");
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_HDBLOCKSIZE"));
+ wx_sendmessage(h, WX_WM_SHOW, 0, (LONG_PARAM)1);
+ }
+ else /* Hide it otherwise. */
+ {
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_HDBLOCKSIZELABEL"));
+ wx_sendmessage(h, WX_WM_SETTEXT, 0, (LONG_PARAM)" ");
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_HDBLOCKSIZE"));
+ wx_sendmessage(h, WX_WM_SHOW, 0, (LONG_PARAM)0);
+ }
+
+ return TRUE;
+ }
break;
}
@@ -1690,12 +2104,12 @@ static int hdsize_dlgproc(void* hdlg, int message, INT_PARAM wParam, LONG_PARAM
int hdconf_init(void* hdlg)
{
int c;
-
+
for (c = 0; c < 7; c++)
{
char s[260];
void *h;
-
+
sprintf(s, "IDC_EDIT_SPT[%i]", c);
h = wx_getdlgitem(hdlg, WX_ID(s));
sprintf(s, "%i", hdc[c].spt);
@@ -1741,7 +2155,7 @@ int hdconf_update(void* hdlg)
wx_enablewindow(wx_getdlgitem(hdlg, WX_ID(s)), !is_mfm);
}
- h = wx_getdlgitem(hdlg, WX_ID("IDC_CONFIGUREHDD"));
+ h = wx_getdlgitem(hdlg, WX_ID("IDC_CONFIGUREHDD"));
if (hdd_controller_selected_has_config(hdlg))
wx_enablewindow(h, TRUE);
else
@@ -1753,7 +2167,7 @@ int hdconf_update(void* hdlg)
static int hd_eject(void *hdlg, int drive)
{
char s[80];
-
+
ide_fn[drive][0] = 0;
sprintf(s, "IDC_EDIT_SPT[%i]", drive);
wx_setdlgitemtext(hdlg, WX_ID(s), "0");
@@ -1764,7 +2178,7 @@ static int hd_eject(void *hdlg, int drive)
sprintf(s, "IDC_EDIT_FN[%i]", drive);
wx_setdlgitemtext(hdlg, WX_ID(s), "");
hd_changed = 1;
-
+
return TRUE;
}
@@ -1775,7 +2189,7 @@ static int hd_new(void *hdlg, int drive)
char s[80];
char id[80];
void *h;
-
+
sprintf(id, "IDC_EDIT_SPT[%i]", drive);
h = wx_getdlgitem(hdlg, WX_ID(id));
sprintf(s, "%i", hd_new_spt);
@@ -1804,7 +2218,7 @@ static int hd_new(void *hdlg, int drive)
static int hd_file(void *hdlg, int drive)
{
- if (!getfile(hdlg, "Hard disc image (*.img)|*.img|All files (*.*)|*.*", ""))
+ if (!getfile(hdlg, "Hard disc image (*.img;*.vhd)|*.img;*.vhd|All files (*.*)|*.*", ""))
{
off64_t sz;
FILE *f = fopen64(openfilestring, "rb");
@@ -1813,17 +2227,64 @@ static int hd_file(void *hdlg, int drive)
wx_messagebox(hdlg,"Can't open file for read","PCem error",WX_MB_OK);
return TRUE;
}
- fseeko64(f, -1, SEEK_END);
- sz = ftello64(f) + 1;
- fclose(f);
- check_hd_type(hdlg, sz);
+
+ if (mvhd_file_is_vhd(f))
+ {
+ fclose(f);
+ int vhdError = 0;
+ MVHDMeta *vhd = mvhd_open(openfilestring, false, &vhdError);
+ if (vhd == NULL)
+ {
+ wx_messagebox(hdlg,mvhd_strerr(vhdError),"PCem error",WX_MB_OK);
+ return TRUE;
+ }
+ else if (vhdError == MVHD_ERR_TIMESTAMP)
+ {
+ const char ts_warning[] =
+ "WARNING: VHD PARENT/CHILD TIMESTAMPS DO NOT MATCH!\n\n"
+ "This could indicate that the parent image was modified after this VHD was created.\n\n"
+ "This could also happen if the VHD files were moved/copied, or the differencing VHD was created with DiskPart.\n\n"
+ "Do you wish to fix this error after a file copy or DiskPart creation?";
+ int wx_res = wx_messagebox(hdlg,ts_warning,"PCem error", WX_MB_NODEFAULT);
+ if (wx_res == WX_MB_YES)
+ {
+ int ts_res = mvhd_diff_update_par_timestamp(vhd, &vhdError);
+ if (ts_res != 0)
+ {
+ wx_messagebox(hdlg,"Can't fix VHD timestamps","PCem error",WX_MB_OK);
+ mvhd_close(vhd);
+ return TRUE;
+ }
+ }
+ else
+ {
+ mvhd_close(vhd);
+ return TRUE;
+ }
+
+ }
+ MVHDGeom geom = mvhd_get_geometry(vhd);
+ hd_new_cyl = geom.cyl;
+ hd_new_hpc = geom.heads;
+ hd_new_spt = geom.spt;
+ hd_new_type = 0;
+ adjust_vhd_geometry_for_pcem();
+ mvhd_close(vhd);
+ }
+ else
+ {
+ fseeko64(f, -1, SEEK_END);
+ sz = ftello64(f) + 1;
+ fclose(f);
+ check_hd_type(hdlg, sz);
+ }
if (wx_dialogbox(hdlg, "HdSizeDlg", hdsize_dlgproc) == 1)
{
char s[80];
char id[80];
void *h;
-
+
sprintf(id, "IDC_EDIT_SPT[%i]", drive);
h = wx_getdlgitem(hdlg, WX_ID(id));
sprintf(s, "%i", hd_new_spt);
@@ -1857,7 +2318,7 @@ static int hd_edit(void *hdlg, int drive)
char id[80];
void *h;
int spt, hpc, tracks;
-
+
sprintf(id, "IDC_EDIT_SPT[%i]", drive);
h = wx_getdlgitem(hdlg, WX_ID(id));
wx_sendmessage(h, WX_WM_GETTEXT, 255, (LONG_PARAM)s);
@@ -1875,7 +2336,7 @@ static int hd_edit(void *hdlg, int drive)
h = wx_getdlgitem(hdlg, WX_ID(id));
sprintf(s, "%imb", ((((tracks*hpc)*spt)*512)/1024)/1024);
wx_sendmessage(h, WX_WM_SETTEXT, 0, (LONG_PARAM)s);
-
+
return TRUE;
}
diff --git a/src/wx-createdisc.cc b/src/wx-createdisc.cc
index d9d1a66..f0eb8fc 100644
--- a/src/wx-createdisc.cc
+++ b/src/wx-createdisc.cc
@@ -29,6 +29,7 @@ static struct
{"320 kB", 2*40*8},
{"360 kB", 2*40*9},
{"720 kB", 2*80*9},
+ {"1.2 MB", 2*80*15},
{"1.44 MB", 2*80*18},
{"2.88 MB", 2*80*36},
{"100 MB (Zip)", 2048*96},
diff --git a/src/wx-glslp-parser.c b/src/wx-glslp-parser.c
index dd1fec1..387918a 100644
--- a/src/wx-glslp-parser.c
+++ b/src/wx-glslp-parser.c
@@ -163,9 +163,9 @@ void get_glslp_name(const char* f, char* s, int size)
glslp_t* glslp_parse(const char* f)
{
int i, j, len, sublen;
- char s[512], t[512], z[512];
+ char s[512], t[512], z[540];
- s[511] = 0;
+ memset(s, 0, sizeof(s));
if (endswith(f, ".glsl"))
return glsl_parse(f);
diff --git a/src/wx-glslp-parser.h b/src/wx-glslp-parser.h
index 59ae315..970eb35 100644
--- a/src/wx-glslp-parser.h
+++ b/src/wx-glslp-parser.h
@@ -22,7 +22,7 @@ struct texture {
};
struct shader {
- char shader_fn[512];
+ char shader_fn[1024];
char* shader_program;
char alias[64];
int filter_linear;
diff --git a/src/wx-resources.cpp b/src/wx-resources.cpp
index a5ba214..68deac3 100644
--- a/src/wx-resources.cpp
+++ b/src/wx-resources.cpp
@@ -1784,7 +1784,7 @@ static unsigned char xml_res_file_25[] = {
87,93,129,205,251,40,255,176,89,15,134,167,154,149,127,4,24,0,227,17,114,
29,252,169,144,138,0,0,0,0,73,69,78,68,174,66,96,130};
-static size_t xml_res_size_26 = 137687;
+static size_t xml_res_size_26 = 142917;
static unsigned char xml_res_file_26[] = {
60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101,
110,99,111,100,105,110,103,61,34,85,84,70,45,56,34,63,62,10,60,33,45,45,
@@ -2032,731 +2032,671 @@ static unsigned char xml_res_file_26[] = {
60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,
116,62,10,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,60,
111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,
-34,62,10,32,32,32,32,32,32,60,108,97,98,101,108,62,86,105,100,101,111,60,
-47,108,97,98,101,108,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
-99,108,97,115,115,61,34,119,120,77,101,110,117,34,62,10,32,32,32,32,32,
-32,32,32,60,108,97,98,101,108,62,82,101,115,111,108,117,116,105,111,110,
-60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,
-99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,
-34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,82,69,83,79,76,85,84,
-73,79,78,91,48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
-108,62,79,114,105,103,105,110,97,108,60,47,108,97,98,101,108,62,10,32,32,
-32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,
-111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,
-77,95,86,73,68,95,82,69,83,79,76,85,84,73,79,78,91,49,93,34,62,10,32,32,
-32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,82,101,115,105,122,97,98,
-108,101,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,
-114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,
-32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,
-98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,
-116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,82,69,83,
-79,76,85,84,73,79,78,91,50,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,
-108,97,98,101,108,62,67,117,115,116,111,109,60,47,108,97,98,101,108,62,
-10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,
-97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,115,101,112,97,114,97,116,111,114,34,47,62,10,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,
-101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,
-68,95,82,69,83,79,76,85,84,73,79,78,95,67,85,83,84,79,77,34,62,10,32,32,
-32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,83,101,116,32,99,117,115,
-116,111,109,32,114,101,115,111,108,117,116,105,111,110,46,46,46,60,47,108,
-97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
+34,32,110,97,109,101,61,34,73,68,77,95,67,65,83,83,69,84,84,69,34,62,10,
+32,32,32,32,32,32,60,108,97,98,101,108,62,67,95,97,115,115,101,116,116,
+101,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,
+32,110,97,109,101,61,34,73,68,77,95,67,65,83,83,69,84,84,69,95,76,79,65,
+68,34,62,10,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,76,111,97,
+100,32,116,97,112,101,102,105,108,101,46,46,46,60,47,108,97,98,101,108,
62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,
-117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,82,
-69,77,69,77,66,69,82,34,62,10,32,32,32,32,32,32,32,32,60,108,97,98,101,
-108,62,82,101,109,101,109,98,101,114,32,115,105,122,101,32,38,97,109,112,
-59,38,97,109,112,59,32,112,111,115,105,116,105,111,110,60,47,108,97,98,
-101,108,62,10,32,32,32,32,32,32,32,32,60,99,104,101,99,107,97,98,108,101,
-62,49,60,47,99,104,101,99,107,97,98,108,101,62,10,32,32,32,32,32,32,60,
-47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,115,101,112,97,114,97,116,111,114,34,47,62,10,
-32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,
-86,73,68,95,70,85,76,76,83,67,82,69,69,78,95,84,79,71,71,76,69,34,62,10,
-32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,84,111,103,103,108,101,
-32,102,117,108,108,115,99,114,101,101,110,92,116,67,116,114,108,43,65,108,
-116,43,80,97,103,101,68,111,119,110,60,47,108,97,98,101,108,62,10,32,32,
-32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,111,
-98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,
-116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,70,85,76,
-76,83,67,82,69,69,78,34,62,10,32,32,32,32,32,32,32,32,60,108,97,98,101,
-108,62,70,117,108,108,115,99,114,101,101,110,32,111,110,32,105,110,112,
-117,116,32,103,114,97,98,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,
-32,32,60,99,104,101,99,107,97,98,108,101,62,49,60,47,99,104,101,99,107,
-97,98,108,101,62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
-32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
-101,112,97,114,97,116,111,114,34,47,62,10,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,34,62,10,32,
-32,32,32,32,32,32,32,60,108,97,98,101,108,62,70,117,108,108,115,99,114,
-101,101,110,32,109,111,100,101,60,47,108,97,98,101,108,62,10,32,32,32,32,
-32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
-77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,
-73,68,95,70,83,95,77,79,68,69,91,48,93,34,62,10,32,32,32,32,32,32,32,32,
-32,32,60,108,97,98,101,108,62,95,66,111,114,100,101,114,108,101,115,115,
-60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,
-105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,
-47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,
-99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,
-34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,70,83,95,77,79,68,69,
-91,49,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,
-95,69,120,99,108,117,115,105,118,101,60,47,108,97,98,101,108,62,10,32,32,
-32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,
-111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,111,
-98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,34,
-32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,82,69,78,68,69,82,95,68,
-82,73,86,69,82,34,62,10,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,
-95,82,101,110,100,101,114,32,100,114,105,118,101,114,60,47,108,97,98,101,
-108,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
-115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,
-61,34,73,68,77,95,86,73,68,95,82,69,78,68,69,82,95,68,82,73,86,69,82,91,
-48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,65,
-117,116,111,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,
-60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,
-32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,
-73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,82,69,
-78,68,69,82,95,68,82,73,86,69,82,91,49,93,34,62,10,32,32,32,32,32,32,32,
-32,32,32,60,108,97,98,101,108,62,68,105,114,101,99,116,51,68,60,47,108,
-97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,
-62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,
-98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,
-110,97,109,101,61,34,73,68,77,95,86,73,68,95,82,69,78,68,69,82,95,68,82,
-73,86,69,82,91,50,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,
-101,108,62,79,112,101,110,71,76,60,47,108,97,98,101,108,62,10,32,32,32,
-32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,
-62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
-32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,
-86,73,68,95,82,69,78,68,69,82,95,68,82,73,86,69,82,91,54,93,34,62,10,32,
-32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,79,112,101,110,71,76,
-32,51,46,48,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,
-60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,
-32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,
-73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,82,69,
-78,68,69,82,95,68,82,73,86,69,82,91,53,93,34,62,10,32,32,32,32,32,32,32,
-32,32,32,60,108,97,98,101,108,62,83,111,102,116,119,97,114,101,60,47,108,
-97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,
-62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,
-98,106,101,99,116,62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,67,65,83,83,69,
+84,84,69,95,69,74,69,67,84,34,62,10,32,32,32,32,32,32,32,32,60,108,97,98,
+101,108,62,95,69,106,101,99,116,32,116,97,112,101,60,47,108,97,98,101,108,
+62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,60,
+47,111,98,106,101,99,116,62,10,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,77,101,110,117,34,62,10,32,32,32,32,32,
+32,60,108,97,98,101,108,62,86,105,100,101,111,60,47,108,97,98,101,108,62,
10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,
-77,95,86,73,68,95,86,83,89,78,67,34,62,10,32,32,32,32,32,32,32,32,60,108,
-97,98,101,108,62,95,86,83,121,110,99,60,47,108,97,98,101,108,62,10,32,32,
-32,32,32,32,32,32,60,99,104,101,99,107,97,98,108,101,62,49,60,47,99,104,
-101,99,107,97,98,108,101,62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,
-116,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
+119,120,77,101,110,117,34,62,10,32,32,32,32,32,32,32,32,60,108,97,98,101,
+108,62,82,101,115,111,108,117,116,105,111,110,60,47,108,97,98,101,108,62,
+10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,
-73,68,77,95,86,73,68,95,76,79,83,84,95,70,79,67,85,83,95,68,73,77,34,62,
-10,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,68,105,109,32,100,
-105,115,112,108,97,121,32,111,110,32,108,111,115,116,32,102,111,99,117,
-115,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,99,104,101,
-99,107,97,98,108,101,62,49,60,47,99,104,101,99,107,97,98,108,101,62,10,
-32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,
+73,68,77,95,86,73,68,95,82,69,83,79,76,85,84,73,79,78,91,48,93,34,62,10,
+32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,79,114,105,103,105,
+110,97,108,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,
+60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,
+32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,
111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,
-73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,65,76,
-84,69,82,78,65,84,73,86,69,95,85,80,68,65,84,69,95,76,79,67,75,34,62,10,
-32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,65,108,116,101,114,110,
-97,116,105,118,101,32,117,112,100,97,116,101,45,108,111,99,107,60,47,108,
-97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,99,104,101,99,107,97,98,
-108,101,62,49,60,47,99,104,101,99,107,97,98,108,101,62,10,32,32,32,32,32,
-32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,111,98,106,101,
-99,116,32,99,108,97,115,115,61,34,115,101,112,97,114,97,116,111,114,34,
-47,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
-61,34,119,120,77,101,110,117,34,62,10,32,32,32,32,32,32,32,32,60,108,97,
-98,101,108,62,83,99,97,108,101,32,102,105,108,116,101,114,105,110,103,60,
-47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
-116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,
-32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,83,67,65,76,69,95,77,79,
-68,69,91,48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
-108,62,95,78,101,97,114,101,115,116,60,47,108,97,98,101,108,62,10,32,32,
-32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,
-111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,
-77,95,86,73,68,95,83,67,65,76,69,95,77,79,68,69,91,49,93,34,62,10,32,32,
-32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,76,105,110,101,97,114,
-60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,
-105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,
-47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,
-116,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
-61,34,119,120,77,101,110,117,34,62,10,32,32,32,32,32,32,32,32,60,108,97,
-98,101,108,62,79,117,116,112,117,116,32,115,116,114,101,116,99,104,45,109,
-111,100,101,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,111,
-98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,
-116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,70,83,91,
-48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,
-78,111,110,101,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,
-32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,
-32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
-60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,
-117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,70,
-83,91,49,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
-62,95,52,58,51,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,
-32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,
-32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
-60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,
-117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,70,
-83,91,50,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
-62,95,83,113,117,97,114,101,32,112,105,120,101,108,115,60,47,108,97,98,
+73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,82,69,
+83,79,76,85,84,73,79,78,91,49,93,34,62,10,32,32,32,32,32,32,32,32,32,32,
+60,108,97,98,101,108,62,82,101,115,105,122,97,98,108,101,60,47,108,97,98,
101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,
60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,
101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,
-109,101,61,34,73,68,77,95,86,73,68,95,70,83,91,51,93,34,62,10,32,32,32,
-32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,73,110,116,101,103,101,
-114,32,115,99,97,108,101,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,
-32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,
-32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
-32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,111,98,106,101,
-99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,34,32,110,97,109,
-101,61,34,73,68,77,95,86,73,68,95,83,67,65,76,69,95,77,69,78,85,34,62,10,
-32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,79,117,116,112,117,116,
-32,115,99,97,108,101,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,
-117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,83,
-67,65,76,69,91,48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,
-101,108,62,48,46,53,120,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,
-32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,
-32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,
-101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,
-68,95,83,67,65,76,69,91,49,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,
-108,97,98,101,108,62,49,120,60,47,108,97,98,101,108,62,10,32,32,32,32,32,
-32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,
-10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
-32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
-77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,
-73,68,95,83,67,65,76,69,91,50,93,34,62,10,32,32,32,32,32,32,32,32,32,32,
-60,108,97,98,101,108,62,49,46,53,120,60,47,108,97,98,101,108,62,10,32,32,
-32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,
-111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,
-77,95,86,73,68,95,83,67,65,76,69,91,51,93,34,62,10,32,32,32,32,32,32,32,
-32,32,32,60,108,97,98,101,108,62,50,120,60,47,108,97,98,101,108,62,10,32,
+109,101,61,34,73,68,77,95,86,73,68,95,82,69,83,79,76,85,84,73,79,78,91,
+50,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,
+117,115,116,111,109,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,
+32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,101,112,97,
+114,97,116,111,114,34,47,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,
+34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,82,69,83,79,76,85,84,
+73,79,78,95,67,85,83,84,79,77,34,62,10,32,32,32,32,32,32,32,32,32,32,60,
+108,97,98,101,108,62,83,101,116,32,99,117,115,116,111,109,32,114,101,115,
+111,108,117,116,105,111,110,46,46,46,60,47,108,97,98,101,108,62,10,32,32,
+32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,
+47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,
+110,97,109,101,61,34,73,68,77,95,86,73,68,95,82,69,77,69,77,66,69,82,34,
+62,10,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,82,101,109,101,109,
+98,101,114,32,115,105,122,101,32,38,97,109,112,59,38,97,109,112,59,32,112,
+111,115,105,116,105,111,110,60,47,108,97,98,101,108,62,10,32,32,32,32,32,
+32,32,32,60,99,104,101,99,107,97,98,108,101,62,49,60,47,99,104,101,99,107,
+97,98,108,101,62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+101,112,97,114,97,116,111,114,34,47,62,10,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,
+109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,70,85,76,76,83,67,
+82,69,69,78,95,84,79,71,71,76,69,34,62,10,32,32,32,32,32,32,32,32,60,108,
+97,98,101,108,62,84,111,103,103,108,101,32,102,117,108,108,115,99,114,101,
+101,110,92,116,67,116,114,108,43,65,108,116,43,80,97,103,101,68,111,119,
+110,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,60,47,111,98,106,101,
+99,116,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
+115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,
+34,73,68,77,95,86,73,68,95,70,85,76,76,83,67,82,69,69,78,34,62,10,32,32,
+32,32,32,32,32,32,60,108,97,98,101,108,62,70,117,108,108,115,99,114,101,
+101,110,32,111,110,32,105,110,112,117,116,32,103,114,97,98,60,47,108,97,
+98,101,108,62,10,32,32,32,32,32,32,32,32,60,99,104,101,99,107,97,98,108,
+101,62,49,60,47,99,104,101,99,107,97,98,108,101,62,10,32,32,32,32,32,32,
+60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,115,101,112,97,114,97,116,111,114,34,47,
+62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,119,120,77,101,110,117,34,62,10,32,32,32,32,32,32,32,32,60,108,97,98,
+101,108,62,70,117,108,108,115,99,114,101,101,110,32,109,111,100,101,60,
+47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,
+32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,70,83,95,77,79,68,69,91,
+48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,
+66,111,114,100,101,114,108,101,115,115,60,47,108,97,98,101,108,62,10,32,
32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,
105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,
-68,77,95,86,73,68,95,83,67,65,76,69,91,52,93,34,62,10,32,32,32,32,32,32,
-32,32,32,32,60,108,97,98,101,108,62,50,46,53,120,60,47,108,97,98,101,108,
-62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,
-97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,
-34,73,68,77,95,86,73,68,95,83,67,65,76,69,91,53,93,34,62,10,32,32,32,32,
-32,32,32,32,32,32,60,108,97,98,101,108,62,51,120,60,47,108,97,98,101,108,
-62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,
-97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,
-34,73,68,77,95,86,73,68,95,83,67,65,76,69,91,54,93,34,62,10,32,32,32,32,
-32,32,32,32,32,32,60,108,97,98,101,108,62,51,46,53,120,60,47,108,97,98,
-101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,
-60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,
-109,101,61,34,73,68,77,95,86,73,68,95,83,67,65,76,69,91,55,93,34,62,10,
-32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,52,120,60,47,108,
-97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,
-62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,
-98,106,101,99,116,62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
-10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-115,101,112,97,114,97,116,111,114,34,47,62,10,32,32,32,32,32,32,60,111,
-98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,34,
-32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,34,62,10,32,32,
-32,32,32,32,32,32,60,108,97,98,101,108,62,79,112,101,110,71,76,32,51,46,
-48,32,114,101,110,100,101,114,101,114,60,47,108,97,98,101,108,62,10,32,
-32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-119,120,77,101,110,117,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,
-98,101,108,62,73,110,112,117,116,32,115,116,114,101,116,99,104,45,109,111,
-100,101,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,
-73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,
-51,95,73,78,80,85,84,95,83,84,82,69,84,67,72,91,48,93,34,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,78,111,110,101,60,
-47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,
-100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,
-32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,
-73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,
-51,95,73,78,80,85,84,95,83,84,82,69,84,67,72,91,49,93,34,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,52,58,51,60,47,108,
-97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,
-111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,
-60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,
-98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,
-116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,
-95,73,78,80,85,84,95,83,84,82,69,84,67,72,91,50,93,34,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,83,113,117,97,114,101,
-32,112,105,120,101,108,115,60,47,108,97,98,101,108,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,
-62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
-61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,
-73,68,77,95,86,73,68,95,71,76,51,95,73,78,80,85,84,95,83,84,82,69,84,67,
-72,91,51,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
-108,62,95,73,110,116,101,103,101,114,32,115,99,97,108,101,60,47,108,97,
-98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,
-111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,
-60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,47,111,98,
+68,77,95,86,73,68,95,70,83,95,77,79,68,69,91,49,93,34,62,10,32,32,32,32,
+32,32,32,32,32,32,60,108,97,98,101,108,62,95,69,120,99,108,117,115,105,
+118,101,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,
+114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,
+32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,47,111,
+98,106,101,99,116,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,119,120,77,101,110,117,34,32,110,97,109,101,61,34,
+73,68,77,95,86,73,68,95,82,69,78,68,69,82,95,68,82,73,86,69,82,34,62,10,
+32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,82,101,110,100,101,114,
+32,100,114,105,118,101,114,60,47,108,97,98,101,108,62,10,32,32,32,32,32,
+32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,
+101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,
+68,95,82,69,78,68,69,82,95,68,82,73,86,69,82,91,48,93,34,62,10,32,32,32,
+32,32,32,32,32,32,32,60,108,97,98,101,108,62,65,117,116,111,60,47,108,97,
+98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,
+49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,
106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
-99,108,97,115,115,61,34,119,120,77,101,110,117,34,62,10,32,32,32,32,32,
-32,32,32,32,32,60,108,97,98,101,108,62,73,110,112,117,116,32,115,99,97,
-108,101,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,
-73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,
-51,95,73,78,80,85,84,95,83,67,65,76,69,91,48,93,34,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,60,108,97,98,101,108,62,48,46,53,120,60,47,108,97,
-98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,
-111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,
-60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,
+99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,
+97,109,101,61,34,73,68,77,95,86,73,68,95,82,69,78,68,69,82,95,68,82,73,
+86,69,82,91,49,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
+108,62,68,105,114,101,99,116,51,68,60,47,108,97,98,101,108,62,10,32,32,
+32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,
+111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,
+77,95,86,73,68,95,82,69,78,68,69,82,95,68,82,73,86,69,82,91,50,93,34,62,
+10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,79,112,101,110,
+71,76,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,
+97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,
+106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,
+101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,82,69,78,68,
+69,82,95,68,82,73,86,69,82,91,54,93,34,62,10,32,32,32,32,32,32,32,32,32,
+32,60,108,97,98,101,108,62,79,112,101,110,71,76,32,51,46,48,60,47,108,97,
+98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,
+49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,
+106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,
+97,109,101,61,34,73,68,77,95,86,73,68,95,82,69,78,68,69,82,95,68,82,73,
+86,69,82,91,53,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
+108,62,83,111,102,116,119,97,114,101,60,47,108,97,98,101,108,62,10,32,32,
+32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,
+111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,111,
98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,
-116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,
-95,73,78,80,85,84,95,83,67,65,76,69,91,49,93,34,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,60,108,97,98,101,108,62,49,120,60,47,108,97,98,101,108,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,
-47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
+116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,86,83,89,
+78,67,34,62,10,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,86,83,
+121,110,99,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,99,
+104,101,99,107,97,98,108,101,62,49,60,47,99,104,101,99,107,97,98,108,101,
+62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,
+117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,76,
+79,83,84,95,70,79,67,85,83,95,68,73,77,34,62,10,32,32,32,32,32,32,32,32,
+60,108,97,98,101,108,62,95,68,105,109,32,100,105,115,112,108,97,121,32,
+111,110,32,108,111,115,116,32,102,111,99,117,115,60,47,108,97,98,101,108,
+62,10,32,32,32,32,32,32,32,32,60,99,104,101,99,107,97,98,108,101,62,49,
+60,47,99,104,101,99,107,97,98,108,101,62,10,32,32,32,32,32,32,60,47,111,
+98,106,101,99,116,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,
+109,101,61,34,73,68,77,95,86,73,68,95,65,76,84,69,82,78,65,84,73,86,69,
+95,85,80,68,65,84,69,95,76,79,67,75,34,62,10,32,32,32,32,32,32,32,32,60,
+108,97,98,101,108,62,65,108,116,101,114,110,97,116,105,118,101,32,117,112,
+100,97,116,101,45,108,111,99,107,60,47,108,97,98,101,108,62,10,32,32,32,
+32,32,32,32,32,60,99,104,101,99,107,97,98,108,101,62,49,60,47,99,104,101,
+99,107,97,98,108,101,62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
+62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,115,101,112,97,114,97,116,111,114,34,47,62,10,32,32,32,32,32,32,60,111,
+98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,34,
+62,10,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,83,99,97,108,101,
+32,102,105,108,116,101,114,105,110,103,60,47,108,97,98,101,108,62,10,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,
+77,95,86,73,68,95,83,67,65,76,69,95,77,79,68,69,91,48,93,34,62,10,32,32,
+32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,78,101,97,114,101,115,
+116,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,
+97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,
+106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,
+101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,83,67,65,76,
+69,95,77,79,68,69,91,49,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,
+97,98,101,108,62,95,76,105,110,101,97,114,60,47,108,97,98,101,108,62,10,
+32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,
+100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,
+117,34,62,10,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,79,117,116,
+112,117,116,32,115,116,114,101,116,99,104,45,109,111,100,101,60,47,108,
+97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,
+97,109,101,61,34,73,68,77,95,86,73,68,95,70,83,91,48,93,34,62,10,32,32,
+32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,78,111,110,101,60,47,
+108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,
+111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,
+32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,70,83,91,49,93,34,62,10,
+32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,52,58,51,60,47,
+108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,
+111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,
+32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,70,83,91,50,93,34,62,10,
+32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,83,113,117,97,
+114,101,32,112,105,120,101,108,115,60,47,108,97,98,101,108,62,10,32,32,
+32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,
+111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,
+77,95,86,73,68,95,70,83,91,51,93,34,62,10,32,32,32,32,32,32,32,32,32,32,
+60,108,97,98,101,108,62,95,73,110,116,101,103,101,114,32,115,99,97,108,
+101,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,
+97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,119,120,77,101,110,117,34,32,110,97,109,101,61,34,73,68,77,
+95,86,73,68,95,83,67,65,76,69,95,77,69,78,85,34,62,10,32,32,32,32,32,32,
+32,32,60,108,97,98,101,108,62,79,117,116,112,117,116,32,115,99,97,108,101,
+60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,
+34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,83,67,65,76,69,91,48,
+93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,48,46,
+53,120,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,
+97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,
+106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,
+101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,83,67,65,76,
+69,91,49,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
+62,49,120,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,
+114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,
+32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,
+98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,
+116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,83,67,65,
+76,69,91,50,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
+108,62,49,46,53,120,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,
+32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,
+110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,
+95,83,67,65,76,69,91,51,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,
+97,98,101,108,62,50,120,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,
+32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,
+101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,
+68,95,83,67,65,76,69,91,52,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,
+108,97,98,101,108,62,50,46,53,120,60,47,108,97,98,101,108,62,10,32,32,32,
+32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,
+62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
+120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,
+86,73,68,95,83,67,65,76,69,91,53,93,34,62,10,32,32,32,32,32,32,32,32,32,
+32,60,108,97,98,101,108,62,51,120,60,47,108,97,98,101,108,62,10,32,32,32,
+32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,
+62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
+120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,
+86,73,68,95,83,67,65,76,69,91,54,93,34,62,10,32,32,32,32,32,32,32,32,32,
+32,60,108,97,98,101,108,62,51,46,53,120,60,47,108,97,98,101,108,62,10,32,
+32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,
+105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,
+68,77,95,86,73,68,95,83,67,65,76,69,91,55,93,34,62,10,32,32,32,32,32,32,
+32,32,32,32,60,108,97,98,101,108,62,52,120,60,47,108,97,98,101,108,62,10,
+32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,
+100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,101,112,97,114,
+97,116,111,114,34,47,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,77,101,110,117,34,32,110,97,109,101,61,
+34,73,68,77,95,86,73,68,95,71,76,51,34,62,10,32,32,32,32,32,32,32,32,60,
+108,97,98,101,108,62,79,112,101,110,71,76,32,51,46,48,32,114,101,110,100,
+101,114,101,114,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,
+111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,
+34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,73,110,112,
+117,116,32,115,116,114,101,116,99,104,45,109,111,100,101,60,47,108,97,98,
+101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,
+97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,95,73,78,80,85,84,95,
+83,84,82,69,84,67,72,91,48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,60,108,97,98,101,108,62,95,78,111,110,101,60,47,108,97,98,101,108,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,
+114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,
+110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,95,73,78,80,85,84,
+95,83,84,82,69,84,67,72,91,49,93,34,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,60,108,97,98,101,108,62,95,52,58,51,60,47,108,97,98,101,108,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,
+97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
+99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,
+97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,95,73,78,80,85,84,95,
+83,84,82,69,84,67,72,91,50,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,60,108,97,98,101,108,62,95,83,113,117,97,114,101,32,112,105,120,101,
+108,115,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
+77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,
+73,68,95,71,76,51,95,73,78,80,85,84,95,83,84,82,69,84,67,72,91,51,93,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,73,
+110,116,101,103,101,114,32,115,99,97,108,101,60,47,108,97,98,101,108,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,
+114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
+61,34,119,120,77,101,110,117,34,62,10,32,32,32,32,32,32,32,32,32,32,60,
+108,97,98,101,108,62,73,110,112,117,116,32,115,99,97,108,101,60,47,108,
+97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,
32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,95,73,78,80,85,
-84,95,83,67,65,76,69,91,50,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,60,108,97,98,101,108,62,49,46,53,120,60,47,108,97,98,101,108,62,10,32,
+84,95,83,67,65,76,69,91,48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,60,108,97,98,101,108,62,48,46,53,120,60,47,108,97,98,101,108,62,10,32,
32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,
97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,
97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,95,73,78,80,85,84,95,
-83,67,65,76,69,91,51,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,
-108,97,98,101,108,62,50,120,60,47,108,97,98,101,108,62,10,32,32,32,32,32,
+83,67,65,76,69,91,49,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,
+108,97,98,101,108,62,49,120,60,47,108,97,98,101,108,62,10,32,32,32,32,32,
32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,
62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,
73,68,77,95,86,73,68,95,71,76,51,95,73,78,80,85,84,95,83,67,65,76,69,91,
-52,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
-62,50,46,53,120,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,
+50,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
+62,49,46,53,120,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,
32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,
32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,
-86,73,68,95,71,76,51,95,73,78,80,85,84,95,83,67,65,76,69,91,53,93,34,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,51,120,60,
+86,73,68,95,71,76,51,95,73,78,80,85,84,95,83,67,65,76,69,91,51,93,34,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,50,120,60,
47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,
100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,
32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,
111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,
73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,
-51,95,73,78,80,85,84,95,83,67,65,76,69,91,54,93,34,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,60,108,97,98,101,108,62,51,46,53,120,60,47,108,97,
+51,95,73,78,80,85,84,95,83,67,65,76,69,91,52,93,34,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,60,108,97,98,101,108,62,50,46,53,120,60,47,108,97,
98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,
111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,
60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,
98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,
116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,
-95,73,78,80,85,84,95,83,67,65,76,69,91,55,93,34,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,60,108,97,98,101,108,62,52,120,60,47,108,97,98,101,108,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,
-47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,119,120,77,101,110,117,34,62,10,32,32,32,32,32,32,32,32,32,32,
-60,108,97,98,101,108,62,83,104,97,100,101,114,32,114,101,102,114,101,115,
-104,32,114,97,116,101,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,
-101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,
-68,95,71,76,51,95,83,72,65,68,69,82,95,82,69,70,82,69,83,72,95,82,65,84,
-69,91,48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
-108,62,83,97,109,101,32,97,115,32,101,109,117,108,97,116,101,100,32,100,
-105,115,112,108,97,121,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,
-62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
-61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,
-73,68,77,95,86,73,68,95,71,76,51,95,83,72,65,68,69,82,95,82,69,70,82,69,
-83,72,95,82,65,84,69,91,49,48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,60,108,97,98,101,108,62,49,48,32,104,122,60,47,108,97,98,101,108,
+95,73,78,80,85,84,95,83,67,65,76,69,91,53,93,34,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,60,108,97,98,101,108,62,51,120,60,47,108,97,98,101,108,
62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,
47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,
-32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,95,83,72,65,68,
-69,82,95,82,69,70,82,69,83,72,95,82,65,84,69,91,50,53,93,34,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,50,53,32,104,122,
+32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,95,73,78,80,85,
+84,95,83,67,65,76,69,91,54,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,60,108,97,98,101,108,62,51,46,53,120,60,47,108,97,98,101,108,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,
+97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
+99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,
+97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,95,73,78,80,85,84,95,
+83,67,65,76,69,91,55,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,
+108,97,98,101,108,62,52,120,60,47,108,97,98,101,108,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,
+62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,
+110,117,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,
+83,104,97,100,101,114,32,114,101,102,114,101,115,104,32,114,97,116,101,
+60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,
+109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,95,83,72,
+65,68,69,82,95,82,69,70,82,69,83,72,95,82,65,84,69,91,48,93,34,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,83,97,109,101,
+32,97,115,32,101,109,117,108,97,116,101,100,32,100,105,115,112,108,97,121,
60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,
97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,
32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,
117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,
-76,51,95,83,72,65,68,69,82,95,82,69,70,82,69,83,72,95,82,65,84,69,91,51,
+76,51,95,83,72,65,68,69,82,95,82,69,70,82,69,83,72,95,82,65,84,69,91,49,
48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
-62,51,48,32,104,122,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,
+62,49,48,32,104,122,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,
32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,
10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,
68,77,95,86,73,68,95,71,76,51,95,83,72,65,68,69,82,95,82,69,70,82,69,83,
-72,95,82,65,84,69,91,53,48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,60,108,97,98,101,108,62,53,48,32,104,122,60,47,108,97,98,101,108,62,
+72,95,82,65,84,69,91,50,53,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,60,108,97,98,101,108,62,50,53,32,104,122,60,47,108,97,98,101,108,62,
10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,
114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,
110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,95,83,72,65,68,69,
-82,95,82,69,70,82,69,83,72,95,82,65,84,69,91,54,48,93,34,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,54,48,32,104,122,60,
+82,95,82,69,70,82,69,83,72,95,82,65,84,69,91,51,48,93,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,51,48,32,104,122,60,
47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,
100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,
32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,
111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,
73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,
-51,95,83,72,65,68,69,82,95,82,69,70,82,69,83,72,95,82,65,84,69,91,55,50,
+51,95,83,72,65,68,69,82,95,82,69,70,82,69,83,72,95,82,65,84,69,91,53,48,
93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,
-55,50,32,104,122,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,
+53,48,32,104,122,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,
32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,
32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,
77,95,86,73,68,95,71,76,51,95,83,72,65,68,69,82,95,82,69,70,82,69,83,72,
-95,82,65,84,69,91,56,53,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-60,108,97,98,101,108,62,56,53,32,104,122,60,47,108,97,98,101,108,62,10,
+95,82,65,84,69,91,54,48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+60,108,97,98,101,108,62,54,48,32,104,122,60,47,108,97,98,101,108,62,10,
32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,
97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
-99,116,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
-32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
-34,115,101,112,97,114,97,116,111,114,34,47,62,10,32,32,32,32,32,32,32,32,
-60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,
-117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,
-76,51,95,83,72,65,68,69,82,95,77,65,78,65,71,69,82,34,62,10,32,32,32,32,
-32,32,32,32,32,32,60,108,97,98,101,108,62,83,104,97,100,101,114,32,109,
-97,110,97,103,101,114,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,
-32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,
-117,34,62,10,32,32,32,32,32,32,60,108,97,98,101,108,62,83,111,117,110,100,
-60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,119,120,77,101,110,117,34,62,10,32,32,32,32,
-32,32,32,32,60,108,97,98,101,108,62,95,66,117,102,102,101,114,32,108,101,
-110,103,116,104,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,
+99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,
+97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,95,83,72,65,68,69,82,
+95,82,69,70,82,69,83,72,95,82,65,84,69,91,55,50,93,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,55,50,32,104,122,60,47,
+108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,
+105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,
+98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,
+116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,
+95,83,72,65,68,69,82,95,82,69,70,82,69,83,72,95,82,65,84,69,91,56,53,93,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,56,
+53,32,104,122,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,
+32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
+32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,
+111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,101,112,97,114,97,
+116,111,114,34,47,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,
+110,97,109,101,61,34,73,68,77,95,86,73,68,95,71,76,51,95,83,72,65,68,69,
+82,95,77,65,78,65,71,69,82,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,
+97,98,101,108,62,83,104,97,100,101,114,32,109,97,110,97,103,101,114,60,
+47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
+99,116,62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
+32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,34,62,10,32,32,32,
+32,32,32,60,108,97,98,101,108,62,83,111,117,110,100,60,47,108,97,98,101,
+108,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
+61,34,119,120,77,101,110,117,34,62,10,32,32,32,32,32,32,32,32,60,108,97,
+98,101,108,62,95,66,117,102,102,101,114,32,108,101,110,103,116,104,60,47,
+108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,
+110,97,109,101,61,34,73,68,77,95,83,78,68,95,66,85,70,91,48,93,34,62,10,
+32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,53,48,32,109,115,
+60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,
+105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,
+47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,
+34,32,110,97,109,101,61,34,73,68,77,95,83,78,68,95,66,85,70,91,49,93,34,
+62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,49,48,48,
+32,109,115,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,
+60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,
+32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,
111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,
73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,83,78,68,95,66,85,
-70,91,48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
-62,95,53,48,32,109,115,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,
-32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,
-32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,
-101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,83,78,
-68,95,66,85,70,91,49,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,
-98,101,108,62,95,49,48,48,32,109,115,60,47,108,97,98,101,108,62,10,32,32,
-32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,
-111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,
-77,95,83,78,68,95,66,85,70,91,50,93,34,62,10,32,32,32,32,32,32,32,32,32,
-32,60,108,97,98,101,108,62,95,50,48,48,32,109,115,60,47,108,97,98,101,108,
-62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,
-97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,
-34,73,68,77,95,83,78,68,95,66,85,70,91,51,93,34,62,10,32,32,32,32,32,32,
-32,32,32,32,60,108,97,98,101,108,62,95,52,48,48,32,109,115,60,47,108,97,
-98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,
-49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
-32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,77,101,110,117,34,62,10,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
-62,95,79,117,116,112,117,116,32,108,101,118,101,108,60,47,108,97,98,101,
-108,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
-115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,
-61,34,73,68,77,95,83,78,68,95,71,65,73,78,91,48,93,34,62,10,32,32,32,32,
-32,32,32,32,32,32,60,108,97,98,101,108,62,95,78,111,114,109,97,108,60,47,
-108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,
-111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,
-111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
-116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,
-32,110,97,109,101,61,34,73,68,77,95,83,78,68,95,71,65,73,78,91,49,93,34,
-62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,43,95,50,32,
-100,66,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,
-97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,
-32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,
-106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,
-101,109,34,32,110,97,109,101,61,34,73,68,77,95,83,78,68,95,71,65,73,78,
-91,50,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,
-43,95,52,32,100,66,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,
-32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,
-32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,
-117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,83,78,68,95,71,
-65,73,78,91,51,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
-108,62,43,95,54,32,100,66,60,47,108,97,98,101,108,62,10,32,32,32,32,32,
+70,91,50,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
+62,95,50,48,48,32,109,115,60,47,108,97,98,101,108,62,10,32,32,32,32,32,
32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,
10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,83,
-78,68,95,71,65,73,78,91,52,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,
-108,97,98,101,108,62,43,95,56,32,100,66,60,47,108,97,98,101,108,62,10,32,
+78,68,95,66,85,70,91,51,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,
+97,98,101,108,62,95,52,48,48,32,109,115,60,47,108,97,98,101,108,62,10,32,
32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,
105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
-32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
-34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,
-68,77,95,83,78,68,95,71,65,73,78,91,53,93,34,62,10,32,32,32,32,32,32,32,
-32,32,32,60,108,97,98,101,108,62,43,95,49,48,32,100,66,60,47,108,97,98,
-101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,
-60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,
-109,101,61,34,73,68,77,95,83,78,68,95,71,65,73,78,91,54,93,34,62,10,32,
-32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,43,49,50,32,100,66,60,
-47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,
+32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,
+111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,
+34,62,10,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,79,117,116,
+112,117,116,32,108,101,118,101,108,60,47,108,97,98,101,108,62,10,32,32,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
+120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,
+83,78,68,95,71,65,73,78,91,48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,
+60,108,97,98,101,108,62,95,78,111,114,109,97,108,60,47,108,97,98,101,108,
+62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,
+97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
+62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
+115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,
+34,73,68,77,95,83,78,68,95,71,65,73,78,91,49,93,34,62,10,32,32,32,32,32,
+32,32,32,32,32,60,108,97,98,101,108,62,43,95,50,32,100,66,60,47,108,97,
+98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,
+49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,
+106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,
+97,109,101,61,34,73,68,77,95,83,78,68,95,71,65,73,78,91,50,93,34,62,10,
+32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,43,95,52,32,100,66,
+60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,
105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,
47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,
99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,
-34,32,110,97,109,101,61,34,73,68,77,95,83,78,68,95,71,65,73,78,91,55,93,
-34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,43,49,52,
+34,32,110,97,109,101,61,34,73,68,77,95,83,78,68,95,71,65,73,78,91,51,93,
+34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,43,95,54,
32,100,66,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,
114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,
32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,
98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,
116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,83,78,68,95,71,65,73,
-78,91,56,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
-62,43,49,54,32,100,66,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,
+78,91,52,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
+62,43,95,56,32,100,66,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,
32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,
32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,
110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,83,78,68,
-95,71,65,73,78,91,57,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,
-98,101,108,62,43,49,56,32,100,66,60,47,108,97,98,101,108,62,10,32,32,32,
-32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,
-62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
-32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,119,120,77,101,110,117,34,62,10,32,32,32,32,32,32,60,108,97,98,
-101,108,62,77,105,115,99,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,
-60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,
-117,34,62,10,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,83,99,114,
-101,101,110,115,104,111,116,60,47,108,97,98,101,108,62,10,32,32,32,32,32,
+95,71,65,73,78,91,53,93,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,
+98,101,108,62,43,95,49,48,32,100,66,60,47,108,97,98,101,108,62,10,32,32,
+32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,
+111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,
+77,95,83,78,68,95,71,65,73,78,91,54,93,34,62,10,32,32,32,32,32,32,32,32,
+32,32,60,108,97,98,101,108,62,43,49,50,32,100,66,60,47,108,97,98,101,108,
+62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,
+97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
+62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
+115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,
+34,73,68,77,95,83,78,68,95,71,65,73,78,91,55,93,34,62,10,32,32,32,32,32,
+32,32,32,32,32,60,108,97,98,101,108,62,43,49,52,32,100,66,60,47,108,97,
+98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,
+49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,47,111,98,
+106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,
+97,109,101,61,34,73,68,77,95,83,78,68,95,71,65,73,78,91,56,93,34,62,10,
+32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,43,49,54,32,100,66,
+60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,114,97,100,
+105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,60,
+47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,
+34,32,110,97,109,101,61,34,73,68,77,95,83,78,68,95,71,65,73,78,91,57,93,
+34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,43,49,56,
+32,100,66,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,
+114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,
+32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,47,111,
+98,106,101,99,116,62,10,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,
-101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,83,67,
-82,69,69,78,83,72,79,84,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,
-98,101,108,62,95,84,97,107,101,32,115,99,114,101,101,110,115,104,111,116,
-92,116,67,116,114,108,43,65,108,116,43,80,97,103,101,85,112,60,47,108,97,
-98,101,108,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
-10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
-61,34,119,120,77,101,110,117,34,62,10,32,32,32,32,32,32,32,32,32,32,60,
-108,97,98,101,108,62,95,70,111,114,109,97,116,60,47,108,97,98,101,108,62,
-10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
-115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,
-61,34,73,68,77,95,83,67,82,69,69,78,83,72,79,84,95,70,79,82,77,65,84,91,
-48,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
-62,80,78,71,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,
+101,110,117,34,62,10,32,32,32,32,32,32,60,108,97,98,101,108,62,77,105,115,
+99,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,34,62,10,32,32,32,
+32,32,32,32,32,60,108,97,98,101,108,62,95,83,99,114,101,101,110,115,104,
+111,116,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,60,111,98,
+106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,
+101,109,34,32,110,97,109,101,61,34,73,68,77,95,83,67,82,69,69,78,83,72,
+79,84,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,
+84,97,107,101,32,115,99,114,101,101,110,115,104,111,116,92,116,67,116,114,
+108,43,65,108,116,43,80,97,103,101,85,112,60,47,108,97,98,101,108,62,10,
32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,
+101,110,117,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
+62,95,70,111,114,109,97,116,60,47,108,97,98,101,108,62,10,32,32,32,32,32,
32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,
-83,67,82,69,69,78,83,72,79,84,95,70,79,82,77,65,84,91,49,93,34,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,84,73,70,70,60,
-47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,
-100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,
-32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,
-73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,83,67,82,69,69,78,
-83,72,79,84,95,70,79,82,77,65,84,91,50,93,34,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,60,108,97,98,101,108,62,66,77,80,60,47,108,97,98,101,108,
+83,67,82,69,69,78,83,72,79,84,95,70,79,82,77,65,84,91,48,93,34,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,80,78,71,60,47,
+108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,
+105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,
+98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,
+116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,83,67,82,69,69,78,83,
+72,79,84,95,70,79,82,77,65,84,91,49,93,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,60,108,97,98,101,108,62,84,73,70,70,60,47,108,97,98,101,108,
62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,
47,114,97,100,105,111,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,
32,110,97,109,101,61,34,73,68,77,95,83,67,82,69,69,78,83,72,79,84,95,70,
-79,82,77,65,84,91,51,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,
-108,97,98,101,108,62,74,80,71,60,47,108,97,98,101,108,62,10,32,32,32,32,
+79,82,77,65,84,91,50,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,
+108,97,98,101,108,62,66,77,80,60,47,108,97,98,101,108,62,10,32,32,32,32,
32,32,32,32,32,32,32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,
111,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
-10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
-32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
-77,101,110,117,73,116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,83,
-67,82,69,69,78,83,72,79,84,95,70,76,65,83,72,34,62,10,32,32,32,32,32,32,
-32,32,32,32,60,108,97,98,101,108,62,70,108,97,115,104,32,115,99,114,101,
-101,110,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,
-99,104,101,99,107,97,98,108,101,62,49,60,47,99,104,101,99,107,97,98,108,
-101,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,111,
+10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,110,97,109,101,
+61,34,73,68,77,95,83,67,82,69,69,78,83,72,79,84,95,70,79,82,77,65,84,91,
+51,93,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
+62,74,80,71,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,60,114,97,100,105,111,62,49,60,47,114,97,100,105,111,62,10,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,
98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,
-116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,83,84,65,84,85,83,34,
-62,10,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,95,77,97,99,104,105,
-110,101,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,60,
-47,111,98,106,101,99,116,62,10,32,32,60,105,100,115,45,114,97,110,103,101,
-32,110,97,109,101,61,34,73,68,67,95,72,68,80,65,78,69,76,34,32,115,116,
-97,114,116,61,34,49,48,34,47,62,10,32,32,60,105,100,115,45,114,97,110,103,
-101,32,110,97,109,101,61,34,73,68,67,95,67,79,77,66,79,68,82,73,86,69,84,
-89,80,69,34,32,115,116,97,114,116,61,34,49,48,48,34,47,62,10,32,32,60,105,
-100,115,45,114,97,110,103,101,32,110,97,109,101,61,34,73,68,67,95,69,68,
-73,84,95,70,78,34,32,115,116,97,114,116,61,34,51,48,48,34,47,62,10,32,32,
-60,105,100,115,45,114,97,110,103,101,32,110,97,109,101,61,34,73,68,67,95,
-70,73,76,69,34,32,115,116,97,114,116,61,34,52,48,48,34,47,62,10,32,32,60,
-105,100,115,45,114,97,110,103,101,32,110,97,109,101,61,34,73,68,67,95,69,
-74,69,67,84,34,32,115,116,97,114,116,61,34,53,48,48,34,47,62,10,32,32,60,
-105,100,115,45,114,97,110,103,101,32,110,97,109,101,61,34,73,68,67,95,78,
-69,87,34,32,115,116,97,114,116,61,34,54,48,48,34,47,62,10,32,32,60,105,
-100,115,45,114,97,110,103,101,32,110,97,109,101,61,34,73,68,67,95,69,68,
-73,84,95,83,80,84,34,32,115,116,97,114,116,61,34,55,48,48,34,47,62,10,32,
-32,60,105,100,115,45,114,97,110,103,101,32,110,97,109,101,61,34,73,68,67,
-95,69,68,73,84,95,72,80,67,34,32,115,116,97,114,116,61,34,56,48,48,34,47,
-62,10,32,32,60,105,100,115,45,114,97,110,103,101,32,110,97,109,101,61,34,
-73,68,67,95,69,68,73,84,95,67,89,76,34,32,115,116,97,114,116,61,34,57,48,
+116,101,109,34,32,110,97,109,101,61,34,73,68,77,95,83,67,82,69,69,78,83,
+72,79,84,95,70,76,65,83,72,34,62,10,32,32,32,32,32,32,32,32,32,32,60,108,
+97,98,101,108,62,70,108,97,115,104,32,115,99,114,101,101,110,60,47,108,
+97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,60,99,104,101,99,107,
+97,98,108,101,62,49,60,47,99,104,101,99,107,97,98,108,101,62,10,32,32,32,
+32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,119,120,77,101,110,117,73,116,101,109,34,32,
+110,97,109,101,61,34,73,68,77,95,83,84,65,84,85,83,34,62,10,32,32,32,32,
+32,32,32,32,60,108,97,98,101,108,62,95,77,97,99,104,105,110,101,60,47,108,
+97,98,101,108,62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
+32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101,
+99,116,62,10,32,32,60,105,100,115,45,114,97,110,103,101,32,110,97,109,101,
+61,34,73,68,67,95,72,68,80,65,78,69,76,34,32,115,116,97,114,116,61,34,49,
48,34,47,62,10,32,32,60,105,100,115,45,114,97,110,103,101,32,110,97,109,
-101,61,34,73,68,67,95,84,69,88,84,95,83,73,90,69,34,32,115,116,97,114,116,
-61,34,49,48,48,48,34,47,62,10,32,32,60,105,100,115,45,114,97,110,103,101,
-32,110,97,109,101,61,34,73,68,67,95,72,68,68,95,76,65,66,69,76,34,32,115,
-116,97,114,116,61,34,49,49,48,48,34,47,62,10,32,32,60,111,98,106,101,99,
-116,32,99,108,97,115,115,61,34,119,120,68,105,97,108,111,103,34,32,110,
-97,109,101,61,34,67,111,110,102,105,103,117,114,101,68,108,103,34,62,10,
-32,32,32,32,60,115,116,121,108,101,62,119,120,68,69,70,65,85,76,84,95,68,
-73,65,76,79,71,95,83,84,89,76,69,60,47,115,116,121,108,101,62,10,32,32,
-32,32,60,116,105,116,108,101,62,67,111,110,102,105,103,117,114,101,32,80,
-67,101,109,60,47,116,105,116,108,101,62,10,32,32,32,32,60,99,101,110,116,
-101,114,101,100,62,49,60,47,99,101,110,116,101,114,101,100,62,10,32,32,
-32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,80,97,
-110,101,108,34,32,110,97,109,101,61,34,82,79,79,84,95,80,65,78,69,76,34,
-62,10,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
-34,119,120,70,108,101,120,71,114,105,100,83,105,122,101,114,34,62,10,32,
-32,32,32,32,32,32,32,60,114,111,119,115,62,48,60,47,114,111,119,115,62,
-10,32,32,32,32,32,32,32,32,60,99,111,108,115,62,49,60,47,99,111,108,115,
-62,10,32,32,32,32,32,32,32,32,60,118,103,97,112,62,48,60,47,118,103,97,
-112,62,10,32,32,32,32,32,32,32,32,60,104,103,97,112,62,48,60,47,104,103,
-97,112,62,10,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,
-111,108,115,47,62,10,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,
-101,114,111,119,115,47,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,
-99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,
-62,10,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,
-47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,60,102,108,
-97,103,62,119,120,65,76,76,124,119,120,69,88,80,65,78,68,60,47,102,108,
-97,103,62,10,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,
-53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,78,111,116,101,
-98,111,111,107,34,32,110,97,109,101,61,34,73,68,67,95,78,79,84,69,66,79,
-79,75,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,
-62,119,120,78,66,95,68,69,70,65,85,76,84,60,47,115,116,121,108,101,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
-97,115,115,61,34,110,111,116,101,98,111,111,107,112,97,103,101,34,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,101,108,101,99,116,101,
-100,62,49,60,47,115,101,108,101,99,116,101,100,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,62,119,120,45,114,101,
-115,111,117,114,99,101,115,46,99,112,112,36,105,99,111,110,115,95,51,50,
-120,51,50,95,109,111,116,104,101,114,98,111,97,114,100,46,112,110,103,60,
-47,98,105,116,109,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,80,97,110,101,
-108,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,
-121,108,101,62,119,120,84,65,66,95,84,82,65,86,69,82,83,65,76,60,47,115,
-116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,108,101,120,
-71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,114,111,119,115,62,48,60,47,114,111,119,115,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,
-115,62,51,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,118,103,97,112,62,48,60,47,118,103,97,112,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,103,97,112,62,
-48,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,115,62,49,60,47,
-103,114,111,119,97,98,108,101,99,111,108,115,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111,
-119,115,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
-105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
-110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,95,
-67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
-100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-115,105,122,101,62,56,48,44,45,49,60,47,115,105,122,101,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
-108,62,77,97,99,104,105,110,101,58,60,47,108,97,98,101,108,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,
-97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,
-34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
-62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
-62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,105,101,110,
-116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,114,105,101,110,
-116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,
-112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,
-102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
-101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,
-67,79,77,66,79,49,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,67,66,
-95,68,82,79,80,68,79,87,78,124,119,120,67,66,95,82,69,65,68,79,78,76,89,
-60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,51,53,48,44,
-45,49,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,
-116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
-65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+101,61,34,73,68,67,95,67,79,77,66,79,68,82,73,86,69,84,89,80,69,34,32,115,
+116,97,114,116,61,34,49,48,48,34,47,62,10,32,32,60,105,100,115,45,114,97,
+110,103,101,32,110,97,109,101,61,34,73,68,67,95,69,68,73,84,95,70,78,34,
+32,115,116,97,114,116,61,34,51,48,48,34,47,62,10,32,32,60,105,100,115,45,
+114,97,110,103,101,32,110,97,109,101,61,34,73,68,67,95,70,73,76,69,34,32,
+115,116,97,114,116,61,34,52,48,48,34,47,62,10,32,32,60,105,100,115,45,114,
+97,110,103,101,32,110,97,109,101,61,34,73,68,67,95,69,74,69,67,84,34,32,
+115,116,97,114,116,61,34,53,48,48,34,47,62,10,32,32,60,105,100,115,45,114,
+97,110,103,101,32,110,97,109,101,61,34,73,68,67,95,78,69,87,34,32,115,116,
+97,114,116,61,34,54,48,48,34,47,62,10,32,32,60,105,100,115,45,114,97,110,
+103,101,32,110,97,109,101,61,34,73,68,67,95,69,68,73,84,95,83,80,84,34,
+32,115,116,97,114,116,61,34,55,48,48,34,47,62,10,32,32,60,105,100,115,45,
+114,97,110,103,101,32,110,97,109,101,61,34,73,68,67,95,69,68,73,84,95,72,
+80,67,34,32,115,116,97,114,116,61,34,56,48,48,34,47,62,10,32,32,60,105,
+100,115,45,114,97,110,103,101,32,110,97,109,101,61,34,73,68,67,95,69,68,
+73,84,95,67,89,76,34,32,115,116,97,114,116,61,34,57,48,48,34,47,62,10,32,
+32,60,105,100,115,45,114,97,110,103,101,32,110,97,109,101,61,34,73,68,67,
+95,84,69,88,84,95,83,73,90,69,34,32,115,116,97,114,116,61,34,49,48,48,48,
+34,47,62,10,32,32,60,105,100,115,45,114,97,110,103,101,32,110,97,109,101,
+61,34,73,68,67,95,72,68,68,95,76,65,66,69,76,34,32,115,116,97,114,116,61,
+34,49,49,48,48,34,47,62,10,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,119,120,68,105,97,108,111,103,34,32,110,97,109,101,61,34,
+67,111,110,102,105,103,117,114,101,68,108,103,34,62,10,32,32,32,32,60,115,
+116,121,108,101,62,119,120,68,69,70,65,85,76,84,95,68,73,65,76,79,71,95,
+83,84,89,76,69,60,47,115,116,121,108,101,62,10,32,32,32,32,60,116,105,116,
+108,101,62,67,111,110,102,105,103,117,114,101,32,80,67,101,109,60,47,116,
+105,116,108,101,62,10,32,32,32,32,60,99,101,110,116,101,114,101,100,62,
+49,60,47,99,101,110,116,101,114,101,100,62,10,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,119,120,80,97,110,101,108,34,32,110,
+97,109,101,61,34,82,79,79,84,95,80,65,78,69,76,34,62,10,32,32,32,32,32,
+32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,108,101,
+120,71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,
+60,114,111,119,115,62,48,60,47,114,111,119,115,62,10,32,32,32,32,32,32,
+32,32,60,99,111,108,115,62,49,60,47,99,111,108,115,62,10,32,32,32,32,32,
+32,32,32,60,118,103,97,112,62,48,60,47,118,103,97,112,62,10,32,32,32,32,
+32,32,32,32,60,104,103,97,112,62,48,60,47,104,103,97,112,62,10,32,32,32,
+32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,115,47,62,10,
+32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111,119,115,
+47,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
+32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,
+111,110,62,10,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
+65,76,76,124,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,
32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,
-100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,105,
-116,109,97,112,66,117,116,116,111,110,34,32,110,97,109,101,61,34,73,68,
-67,95,67,79,78,70,73,71,85,82,69,77,79,68,34,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,62,
-119,120,45,114,101,115,111,117,114,99,101,115,46,99,112,112,36,105,99,111,
-110,115,95,49,54,120,49,54,95,115,101,116,116,105,110,103,95,116,111,111,
-108,115,46,112,110,103,60,47,98,105,116,109,97,112,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,
-108,116,62,48,60,47,100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
-105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
-110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,95,
-67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
-100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-115,105,122,101,62,56,48,44,45,49,60,47,115,105,122,101,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
-108,62,67,80,85,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,
+100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,119,120,78,111,116,101,98,111,111,107,34,32,
+110,97,109,101,61,34,73,68,67,95,78,79,84,69,66,79,79,75,34,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,78,66,95,
+68,69,70,65,85,76,84,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,110,
+111,116,101,98,111,111,107,112,97,103,101,34,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,115,101,108,101,99,116,101,100,62,49,60,47,115,
+101,108,101,99,116,101,100,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,98,105,116,109,97,112,62,119,120,45,114,101,115,111,117,114,99,101,
+115,46,99,112,112,36,105,99,111,110,115,95,51,50,120,51,50,95,109,111,116,
+104,101,114,98,111,97,114,100,46,112,110,103,60,47,98,105,116,109,97,112,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,119,120,80,97,110,101,108,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,
+84,65,66,95,84,82,65,86,69,82,83,65,76,60,47,115,116,121,108,101,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,119,120,70,108,101,120,71,114,105,100,83,105,
+122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,114,111,119,115,62,48,60,47,114,111,119,115,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,115,62,51,60,47,99,
+111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,118,103,97,112,62,48,60,47,118,103,97,112,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,104,103,97,112,62,48,60,47,104,103,
+97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,
+114,111,119,97,98,108,101,99,111,108,115,62,49,60,47,103,114,111,119,97,
+98,108,101,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111,119,115,47,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
+119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,95,67,69,78,84,69,82,
+95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,
+53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
+61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,
+62,56,48,44,45,49,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,77,97,99,
+104,105,110,101,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,
47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
@@ -2783,12 +2723,109 @@ static unsigned char xml_res_file_26[] = {
60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,67,111,109,98,111,
-66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,67,79,77,66,79,67,80,
-85,77,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,67,66,95,68,82,79,
-80,68,79,87,78,124,119,120,67,66,95,82,69,65,68,79,78,76,89,60,47,115,116,
+66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,67,79,77,66,79,49,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,115,116,121,108,101,62,119,120,67,66,95,68,82,79,80,68,79,
+87,78,124,119,120,67,66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,
+101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,115,105,122,101,62,51,53,48,44,45,49,60,47,115,105,122,
+101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,
+110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,
+47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,
+97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,119,120,66,105,116,109,97,112,66,117,
+116,116,111,110,34,32,110,97,109,101,61,34,73,68,67,95,67,79,78,70,73,71,
+85,82,69,77,79,68,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,98,105,116,109,97,112,62,119,120,45,114,101,115,
+111,117,114,99,101,115,46,99,112,112,36,105,99,111,110,115,95,49,54,120,
+49,54,95,115,101,116,116,105,110,103,95,116,111,111,108,115,46,112,110,
+103,60,47,98,105,116,109,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,108,116,62,48,60,
+47,100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
+119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,95,67,69,78,84,69,82,
+95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,
+53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
+61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,
+62,56,48,44,45,49,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,80,85,
+58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,
+112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
+61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,
+60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,
+60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,
+114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,
+105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,114,105,101,110,116,62,119,120,72,79,82,73,90,
+79,78,84,65,76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
+108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,119,120,67,111,109,98,111,66,111,120,
+34,32,110,97,109,101,61,34,73,68,67,95,67,79,77,66,79,67,80,85,77,34,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,115,116,121,108,101,62,119,120,67,66,95,68,82,79,80,68,79,87,
+78,124,119,120,67,66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,101,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,115,105,122,101,62,49,50,48,44,45,49,60,47,115,105,122,101,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,
+116,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,
+101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,
+111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,67,111,109,
+98,111,66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,67,79,77,66,79,
+51,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,67,66,95,68,82,79,80,
+68,79,87,78,124,119,120,67,66,95,82,69,65,68,79,78,76,89,60,47,115,116,
121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,115,105,122,101,62,49,50,48,44,45,49,60,47,115,
+32,32,32,32,32,32,32,32,60,115,105,122,101,62,50,50,48,44,45,49,60,47,115,
105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,
@@ -2796,642 +2833,71 @@ static unsigned char xml_res_file_26[] = {
32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,
-112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,
-102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
-101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,
-67,79,77,66,79,51,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,67,66,
-95,68,82,79,80,68,79,87,78,124,119,120,67,66,95,82,69,65,68,79,78,76,89,
-60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,50,50,48,44,
-45,49,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,
-62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,
-78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
-101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,
-105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
-69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,
-98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,
-111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,65,76,73,71,
-78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,
-111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,119,120,67,104,101,99,107,66,111,120,34,32,110,
-97,109,101,61,34,73,68,67,95,67,72,69,67,75,68,89,78,65,82,69,67,34,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-108,97,98,101,108,62,68,121,110,97,109,105,99,32,114,101,99,111,109,112,
-105,108,101,114,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,104,101,99,107,101,100,62,
-48,60,47,99,104,101,99,107,101,100,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,
-105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
-69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,
-98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,
-111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,65,76,73,71,
-78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,
-111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,
-34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,108,97,98,101,108,62,77,101,109,111,114,121,58,60,47,108,97,98,101,
-108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,
-111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,
-111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,114,105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,
-111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
-34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
-110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
-65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,
-47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
-115,115,61,34,119,120,83,112,105,110,67,116,114,108,34,32,110,97,109,101,
-61,34,73,68,67,95,77,69,77,83,80,73,78,34,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,
-101,62,119,120,83,80,95,65,82,82,79,87,95,75,69,89,83,60,47,115,116,121,
-108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,118,97,108,117,101,62,48,60,47,118,97,108,117,101,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,109,105,110,62,48,60,47,109,105,110,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,109,97,
-120,62,49,48,60,47,109,97,120,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
-98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
-105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,
-48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,
-76,76,32,124,32,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,
-84,73,67,65,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,
-53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
-97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,110,
-97,109,101,61,34,73,68,67,95,84,69,88,84,95,77,66,34,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,
-97,98,101,108,62,77,66,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,
-97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,
-62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,
-78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
-101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,
-34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
-62,119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,95,67,69,78,84,69,
-82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
-62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
-108,62,87,97,105,116,115,116,97,116,101,115,58,60,47,108,97,98,101,108,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
-105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,
-110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
-100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,
-105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,114,
-105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
-105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,
-48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,
-76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,
-98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,119,120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,
-34,73,68,67,95,67,79,77,66,79,87,83,34,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,
-62,119,120,67,66,95,68,82,79,80,68,79,87,78,124,119,120,67,66,95,82,69,
-65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,
-101,62,51,53,48,44,45,49,60,47,115,105,122,101,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,
-117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,116,47,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
-98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,
-34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
-62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
-62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,
-105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
-112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,
-110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
-100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,
-60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
-34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,
-47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,32,124,32,119,
-120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,
-102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,
-106,101,99,116,32,99,108,97,115,115,61,34,119,120,67,104,101,99,107,66,
-111,120,34,32,110,97,109,101,61,34,73,68,67,95,67,72,69,67,75,83,89,78,
-67,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,108,97,98,101,108,62,83,121,110,99,104,114,111,110,105,122,101,
-32,116,105,109,101,32,116,111,32,104,111,115,116,32,99,108,111,99,107,60,
-47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,99,104,101,99,107,101,100,62,48,60,47,99,104,101,
-99,107,101,100,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
-97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,
-47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,
-47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,
-105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
-97,115,115,61,34,110,111,116,101,98,111,111,107,112,97,103,101,34,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,101,108,101,99,116,101,
-100,62,48,60,47,115,101,108,101,99,116,101,100,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,62,119,120,45,114,101,
-115,111,117,114,99,101,115,46,99,112,112,36,105,99,111,110,115,95,51,50,
-120,51,50,95,118,105,100,101,111,95,109,111,100,101,46,112,110,103,60,47,
-98,105,116,109,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,80,97,110,101,
-108,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,
-121,108,101,62,119,120,84,65,66,95,84,82,65,86,69,82,83,65,76,60,47,115,
-116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,108,101,120,
-71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,114,111,119,115,62,48,60,47,114,111,119,115,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,
-115,62,51,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,118,103,97,112,62,48,60,47,118,103,97,112,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,103,97,112,62,
-48,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,115,62,49,60,47,
-103,114,111,119,97,98,108,101,99,111,108,115,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111,
-119,115,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
-105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
-110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,95,
-67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
-100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-115,105,122,101,62,56,48,44,45,49,60,47,115,105,122,101,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
-108,62,68,101,118,105,99,101,58,60,47,108,97,98,101,108,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,
-112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,
-34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
-62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
-62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,105,101,110,
-116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,114,105,101,110,
-116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,
-112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,
-102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
-101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,
-67,79,77,66,79,86,73,68,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,
-67,66,95,68,82,79,80,68,79,87,78,124,119,120,67,66,95,82,69,65,68,79,78,
-76,89,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,51,53,
-48,44,45,49,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
-116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
-99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
-112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
-119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,
-98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,66,105,116,109,97,112,66,117,116,116,111,110,34,32,110,97,109,101,61,
-34,73,68,67,95,67,79,78,70,73,71,85,82,69,86,73,68,34,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,
-97,112,62,119,120,45,114,101,115,111,117,114,99,101,115,46,99,112,112,36,
-105,99,111,110,115,95,49,54,120,49,54,95,115,101,116,116,105,110,103,95,
-116,111,111,108,115,46,112,110,103,60,47,98,105,116,109,97,112,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,
-102,97,117,108,116,62,48,60,47,100,101,102,97,117,108,116,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
-99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
-111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,
-101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,
-105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,65,76,73,
-71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,
-103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
-116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,
-116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,115,105,122,101,62,56,48,44,45,49,60,47,115,105,122,101,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,
-97,98,101,108,62,83,112,101,101,100,58,60,47,108,97,98,101,108,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,
-97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,
-34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
-62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,
-47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-119,120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,73,68,67,
-95,67,79,77,66,79,83,80,68,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,67,66,95,
-68,82,79,80,68,79,87,78,32,124,32,119,120,67,66,95,82,69,65,68,79,78,76,
-89,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,116,
-101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
-97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,
-47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,
-47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,
-105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,
-62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,
-78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
-101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,
-34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
-62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
-62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,105,101,110,
-116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,114,105,101,110,
-116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,
112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,
-102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
-101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,67,104,101,99,107,66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,
-67,72,69,67,75,86,79,79,68,79,79,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,
-86,111,111,100,111,111,32,71,114,97,112,104,105,99,115,60,47,108,97,98,
-101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,99,104,101,99,107,101,100,62,48,60,47,99,104,101,
-99,107,101,100,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
-116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
-61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,
-60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,
+32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,
108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,119,120,66,105,116,109,97,112,66,
-117,116,116,111,110,34,32,110,97,109,101,61,34,73,68,67,95,67,79,78,70,
-73,71,85,82,69,86,79,79,68,79,79,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,62,119,120,
-45,114,101,115,111,117,114,99,101,115,46,99,112,112,36,105,99,111,110,115,
-95,49,54,120,49,54,95,115,101,116,116,105,110,103,95,116,111,111,108,115,
-46,112,110,103,60,47,98,105,116,109,97,112,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,108,116,
-62,48,60,47,100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
-116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
-98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,110,111,116,101,98,111,111,107,112,
-97,103,101,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,101,
-108,101,99,116,101,100,62,48,60,47,115,101,108,101,99,116,101,100,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,62,119,
-120,45,114,101,115,111,117,114,99,101,115,46,99,112,112,36,105,99,111,110,
-115,95,51,50,120,51,50,95,115,111,117,110,100,46,112,110,103,60,47,98,105,
-116,109,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,
-106,101,99,116,32,99,108,97,115,115,61,34,119,120,80,97,110,101,108,34,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,
-101,62,119,120,84,65,66,95,84,82,65,86,69,82,83,65,76,60,47,115,116,121,
-108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,
-106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,108,101,120,71,114,
-105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,114,111,119,115,62,48,60,47,114,111,119,115,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,115,
-62,51,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,118,103,97,112,62,48,60,47,118,103,97,112,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,103,97,112,62,48,
-60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,115,62,49,60,47,103,
-114,111,119,97,98,108,101,99,111,108,115,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111,
-119,115,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
-105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
-110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,95,
-67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
-100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-115,105,122,101,62,56,48,44,45,49,60,47,115,105,122,101,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
-108,62,68,101,118,105,99,101,58,60,47,108,97,98,101,108,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,
-112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,
-34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
-62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
-62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,105,101,110,
-116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,114,105,101,110,
-116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,
-112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,
-102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
-101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,
-67,79,77,66,79,83,78,68,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,
-67,66,95,68,82,79,80,68,79,87,78,124,119,120,67,66,95,82,69,65,68,79,78,
-76,89,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,51,53,
-48,44,45,49,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
-116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
-99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
-112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
-119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,
-98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,66,105,116,109,97,112,66,117,116,116,111,110,34,32,110,97,109,101,61,
-34,73,68,67,95,67,79,78,70,73,71,85,82,69,83,78,68,34,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,
-97,112,62,119,120,45,114,101,115,111,117,114,99,101,115,46,99,112,112,36,
-105,99,111,110,115,95,49,54,120,49,54,95,115,101,116,116,105,110,103,95,
-116,111,111,108,115,46,112,110,103,60,47,98,105,116,109,97,112,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,
-102,97,117,108,116,62,48,60,47,100,101,102,97,117,108,116,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
-99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
-111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,112,97,
-99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
-108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,
-101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,
-115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
-105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,
-112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,
-111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,119,120,67,104,101,99,107,66,111,120,34,32,110,
-97,109,101,61,34,73,68,67,95,67,72,69,67,75,51,34,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
-62,67,77,83,32,47,32,71,97,109,101,32,66,108,97,115,116,101,114,60,47,108,
-97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,99,104,101,99,107,101,100,62,48,60,47,99,104,101,99,107,
-101,100,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
-115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,
-111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,
-102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,
122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
-99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,
-49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,
-68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
-101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,
-34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
-62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,
-47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-119,120,67,104,101,99,107,66,111,120,34,32,110,97,109,101,61,34,73,68,67,
-95,67,72,69,67,75,71,85,83,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,71,114,97,118,105,
-115,32,85,108,116,114,97,115,111,117,110,100,60,47,108,97,98,101,108,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-99,104,101,99,107,101,100,62,48,60,47,99,104,101,99,107,101,100,62,10,32,
+99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,
+105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
+65,76,76,32,124,32,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,
+82,84,73,67,65,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,
+98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
+120,83,116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,56,48,44,
+45,49,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,70,80,85,58,60,47,108,
+97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,
+112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,
+108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,122,101,
+114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,114,105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,
+76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,
+116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,
+103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,
+114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,67,111,109,98,111,66,111,120,34,32,110,
+97,109,101,61,34,73,68,67,95,67,79,77,66,79,70,80,85,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+115,116,121,108,101,62,119,120,67,66,95,68,82,79,80,68,79,87,78,124,119,
+120,67,66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,115,105,122,101,62,49,50,48,44,45,49,60,47,115,105,122,101,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,116,
+47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
@@ -3459,17 +2925,101 @@ static unsigned char xml_res_file_26[] = {
115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,
48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,
+32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,32,124,
+32,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,
+76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
+101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,67,104,101,
+99,107,66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,67,72,69,67,75,
+68,89,78,65,82,69,67,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,68,121,110,97,109,105,99,
+32,114,101,99,111,109,112,105,108,101,114,60,47,108,97,98,101,108,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,
+104,101,99,107,101,100,62,48,60,47,99,104,101,99,107,101,100,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,
+60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,
+47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,32,124,32,119,
+120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,
102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,
10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,
-106,101,99,116,32,99,108,97,115,115,61,34,119,120,67,104,101,99,107,66,
-111,120,34,32,110,97,109,101,61,34,73,68,67,95,67,72,69,67,75,83,83,73,
-34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,108,97,98,101,108,62,73,110,110,111,118,97,116,105,111,110,32,83,
-83,73,45,50,48,48,49,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,104,101,99,107,101,100,
-62,48,60,47,99,104,101,99,107,101,100,62,10,32,32,32,32,32,32,32,32,32,
+106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,
+84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,108,97,98,101,108,62,77,101,109,111,114,121,58,60,
+47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
+98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,
+111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,
+102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,
+106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,122,
+101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,114,105,101,110,116,62,119,120,72,79,82,73,90,79,78,
+84,65,76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,
+116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,
+103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,
+114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,83,112,105,110,67,116,114,108,34,32,110,
+97,109,101,61,34,73,68,67,95,77,69,77,83,80,73,78,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,
+116,121,108,101,62,119,120,83,80,95,65,82,82,79,87,95,75,69,89,83,60,47,
+115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,62,48,60,47,118,
+97,108,117,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,109,105,110,62,48,60,47,109,105,110,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,109,97,120,62,49,48,60,47,109,97,120,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
+99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,
+116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,
+103,62,119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,95,67,69,78,84,
+69,82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,
+116,34,32,110,97,109,101,61,34,73,68,67,95,84,69,88,84,95,77,66,34,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,108,97,98,101,108,62,77,66,60,47,108,97,98,101,108,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
@@ -3494,60 +3044,310 @@ static unsigned char xml_res_file_26[] = {
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,
34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,115,105,122,101,62,56,48,44,45,49,60,47,115,105,122,101,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,
-98,101,108,62,76,80,84,32,68,101,118,105,99,101,58,60,47,108,97,98,101,
-108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
+32,60,108,97,98,101,108,62,87,97,105,116,115,116,97,116,101,115,58,60,47,
+108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,
-111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,
+112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,
+108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,122,101,
+114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,114,105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,
+76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,
+116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,
+103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,
+114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,67,111,109,98,111,66,111,120,34,32,110,
+97,109,101,61,34,73,68,67,95,67,79,77,66,79,87,83,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,
+116,121,108,101,62,119,120,67,66,95,68,82,79,80,68,79,87,78,124,119,120,
+67,66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,115,105,122,101,62,51,53,48,44,45,49,60,47,115,105,122,101,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,116,47,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,
+60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,
+105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,
+111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,
+44,48,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
+115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,
+48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,32,124,
+32,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,
+76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
+101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,67,104,101,
+99,107,66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,67,72,69,67,75,
+83,89,78,67,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,108,97,98,101,108,62,83,121,110,99,104,114,111,110,105,
+122,101,32,116,105,109,101,32,116,111,32,104,111,115,116,32,99,108,111,
+99,107,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,99,104,101,99,107,101,100,62,48,60,47,
+99,104,101,99,107,101,100,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
+110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,
+65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,
+100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
+116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
+106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
+98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
+106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,110,111,116,101,98,111,111,107,112,
+97,103,101,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,101,
+108,101,99,116,101,100,62,48,60,47,115,101,108,101,99,116,101,100,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,62,119,
+120,45,114,101,115,111,117,114,99,101,115,46,99,112,112,36,105,99,111,110,
+115,95,51,50,120,51,50,95,118,105,100,101,111,95,109,111,100,101,46,112,
+110,103,60,47,98,105,116,109,97,112,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
+80,97,110,101,108,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,115,116,121,108,101,62,119,120,84,65,66,95,84,82,65,86,69,82,83,65,
+76,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
+70,108,101,120,71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,114,111,119,115,62,48,60,47,114,
+111,119,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,99,111,108,115,62,51,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,118,103,97,112,62,48,60,47,118,103,
+97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,
+103,97,112,62,48,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,
+115,62,49,60,47,103,114,111,119,97,98,108,101,99,111,108,115,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,
+108,101,114,111,119,115,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,
+112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,
+65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,
+108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,
+120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,115,105,122,101,62,56,48,44,45,49,60,47,115,105,122,101,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,108,97,98,101,108,62,68,101,118,105,99,101,58,60,47,108,97,98,101,108,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
+105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,
+105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,114,
+105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,
+48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,
+76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,
+98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
+115,61,34,119,120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,
+34,73,68,67,95,67,79,77,66,79,86,73,68,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,
+101,62,119,120,67,66,95,68,82,79,80,68,79,87,78,124,119,120,67,66,95,82,
+69,65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,
+122,101,62,51,53,48,44,45,49,60,47,115,105,122,101,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,
+108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,116,47,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
+105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,
+114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,119,120,66,105,116,109,97,112,66,117,116,116,111,110,34,32,
+110,97,109,101,61,34,73,68,67,95,67,79,78,70,73,71,85,82,69,86,73,68,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,98,105,116,109,97,112,62,119,120,45,114,101,115,111,117,114,99,101,115,
+46,99,112,112,36,105,99,111,110,115,95,49,54,120,49,54,95,115,101,116,116,
+105,110,103,95,116,111,111,108,115,46,112,110,103,60,47,98,105,116,109,
+97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,100,101,102,97,117,108,116,62,48,60,47,100,101,102,97,117,108,
+116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
+61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,
+60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,32,124,32,
+119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,
+60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,
+114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,
+105,99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,115,105,122,101,62,56,48,44,45,49,60,47,115,
+105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,108,97,98,101,108,62,83,112,101,101,100,58,60,47,108,97,
+98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,
+112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,
62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,
111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,114,105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,
-111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,99,108,97,115,115,61,34,119,120,67,111,109,98,111,66,111,120,34,32,110,
+97,109,101,61,34,73,68,67,95,67,79,77,66,79,83,80,68,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,
+108,101,62,119,120,67,66,95,68,82,79,80,68,79,87,78,32,124,32,119,120,67,
+66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,
+117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
+62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
+62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,
+105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,
+60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
-110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
-65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,
-47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
-115,115,61,34,119,120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,
-61,34,73,68,67,95,67,79,77,66,79,76,80,84,49,34,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,
-121,108,101,62,119,120,67,66,95,68,82,79,80,68,79,87,78,124,119,120,67,
-66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-115,105,122,101,62,51,53,48,44,45,49,60,47,115,105,122,101,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,116,47,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
-99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
-111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,112,97,
-99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
-108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,
+47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,
+47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,
+122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,114,105,101,110,116,62,119,120,72,79,82,73,90,79,
+78,84,65,76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,
+97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,
101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,
-115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,119,120,67,104,101,99,107,66,111,120,34,32,110,
+97,109,101,61,34,73,68,67,95,67,72,69,67,75,86,79,79,68,79,79,34,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,108,97,98,101,108,62,86,111,111,100,111,111,32,71,114,97,112,104,
+105,99,115,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,104,101,99,107,101,
+100,62,48,60,47,99,104,101,99,107,101,100,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
+116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
+119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,
+98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
+120,66,105,116,109,97,112,66,117,116,116,111,110,34,32,110,97,109,101,61,
+34,73,68,67,95,67,79,78,70,73,71,85,82,69,86,79,79,68,79,79,34,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,
+116,109,97,112,62,119,120,45,114,101,115,111,117,114,99,101,115,46,99,112,
+112,36,105,99,111,110,115,95,49,54,120,49,54,95,115,101,116,116,105,110,
+103,95,116,111,111,108,115,46,112,110,103,60,47,98,105,116,109,97,112,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+100,101,102,97,117,108,116,62,48,60,47,100,101,102,97,117,108,116,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
+106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
@@ -3557,47 +3357,327 @@ static unsigned char xml_res_file_26[] = {
32,32,32,32,60,115,101,108,101,99,116,101,100,62,48,60,47,115,101,108,101,
99,116,101,100,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,
116,109,97,112,62,119,120,45,114,101,115,111,117,114,99,101,115,46,99,112,
-112,36,105,99,111,110,115,95,51,50,120,51,50,95,100,114,105,118,101,46,
+112,36,105,99,111,110,115,95,51,50,120,51,50,95,115,111,117,110,100,46,
112,110,103,60,47,98,105,116,109,97,112,62,10,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,80,97,110,101,108,34,32,110,97,109,101,61,34,80,65,78,69,76,95,68,82,
-73,86,69,83,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-115,116,121,108,101,62,119,120,84,65,66,95,84,82,65,86,69,82,83,65,76,60,
-47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,108,
-101,120,71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,114,111,119,115,62,48,60,47,114,111,
-119,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-99,111,108,115,62,49,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,118,103,97,112,62,48,60,47,118,103,97,
-112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,
-103,97,112,62,48,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,
-115,62,48,60,47,103,114,111,119,97,98,108,101,99,111,108,115,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,
-108,101,114,111,119,115,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+120,80,97,110,101,108,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,115,116,121,108,101,62,119,120,84,65,66,95,84,82,65,86,69,82,83,
+65,76,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
+120,70,108,101,120,71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,114,111,119,115,62,48,60,
+47,114,111,119,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,99,111,108,115,62,51,60,47,99,111,108,115,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,103,97,112,62,48,60,47,118,
+103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,104,103,97,112,62,48,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,
+108,115,62,49,60,47,103,114,111,119,97,98,108,101,99,111,108,115,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,
+97,98,108,101,114,111,119,115,47,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,
+111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,
+65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,
+108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,
+120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,115,105,122,101,62,56,48,44,45,49,60,47,115,105,122,101,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,108,97,98,101,108,62,68,101,118,105,99,101,58,60,47,108,97,98,101,108,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
+105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,
+105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,114,
+105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,
+48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,
+76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,
+98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
+115,61,34,119,120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,
+34,73,68,67,95,67,79,77,66,79,83,78,68,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,
+101,62,119,120,67,66,95,68,82,79,80,68,79,87,78,124,119,120,67,66,95,82,
+69,65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,
+122,101,62,51,53,48,44,45,49,60,47,115,105,122,101,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,
+108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,116,47,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
+105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,
+114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,119,120,66,105,116,109,97,112,66,117,116,116,111,110,34,32,
+110,97,109,101,61,34,73,68,67,95,67,79,78,70,73,71,85,82,69,83,78,68,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,98,105,116,109,97,112,62,119,120,45,114,101,115,111,117,114,99,101,115,
+46,99,112,112,36,105,99,111,110,115,95,49,54,120,49,54,95,115,101,116,116,
+105,110,103,95,116,111,111,108,115,46,112,110,103,60,47,98,105,116,109,
+97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,100,101,102,97,117,108,116,62,48,60,47,100,101,102,97,117,108,
+116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
+61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,
+116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,
+103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,
+48,44,48,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
+110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,
+60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,
+114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,67,104,101,99,
+107,66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,67,72,69,67,75,51,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,108,97,98,101,108,62,67,77,83,32,47,32,71,97,109,101,32,66,108,97,
+115,116,101,114,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,104,101,99,107,101,100,62,
+48,60,47,99,104,101,99,107,101,100,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,
+105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
+69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,
+98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
+106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,
+114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,
+103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
+62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,
+105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,
+112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,
+111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,119,120,67,104,101,99,107,66,111,120,34,32,110,
+97,109,101,61,34,73,68,67,95,67,72,69,67,75,71,85,83,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
+108,62,71,114,97,118,105,115,32,85,108,116,114,97,115,111,117,110,100,60,
+47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,99,104,101,99,107,101,100,62,48,60,47,99,104,101,
+99,107,101,100,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,
+47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,
+47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,
+105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,
+62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,
+78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
+101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
+62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,
+47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+119,120,67,104,101,99,107,66,111,120,34,32,110,97,109,101,61,34,73,68,67,
+95,67,72,69,67,75,83,83,73,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,73,110,110,111,118,
+97,116,105,111,110,32,83,83,73,45,50,48,48,49,60,47,108,97,98,101,108,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+99,104,101,99,107,101,100,62,48,60,47,99,104,101,99,107,101,100,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,
+60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,
+47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,32,124,32,119,
+120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,
+102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,
+106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,
+84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,115,105,122,101,62,56,48,44,45,49,60,47,115,105,122,
+101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,108,97,98,101,108,62,76,80,84,32,68,101,118,105,99,101,58,60,47,108,
+97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,
112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,
108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,98,111,114,100,101,114,62,48,60,47,98,111,114,100,101,114,62,10,
+32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,119,120,70,108,101,120,71,114,105,
-100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,114,111,119,115,62,48,60,47,114,111,119,115,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,99,111,108,115,62,51,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,103,97,112,62,48,60,
-47,118,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,104,103,97,112,62,48,60,47,104,103,97,112,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,
-111,119,97,98,108,101,99,111,108,115,62,49,60,47,103,114,111,119,97,98,
-108,101,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111,119,115,
-47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
+101,99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,122,101,
+114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,114,105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,
+76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,
+116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,
+103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,
+114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,67,111,109,98,111,66,111,120,34,32,110,
+97,109,101,61,34,73,68,67,95,67,79,77,66,79,76,80,84,49,34,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,115,116,121,108,101,62,119,120,67,66,95,68,82,79,80,68,79,87,78,124,
+119,120,67,66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,115,105,122,101,62,51,53,48,44,45,49,60,47,115,105,122,101,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,
+116,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
+106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,
+60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,110,
+111,116,101,98,111,111,107,112,97,103,101,34,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,115,101,108,101,99,116,101,100,62,48,60,47,115,
+101,108,101,99,116,101,100,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,98,105,116,109,97,112,62,119,120,45,114,101,115,111,117,114,99,101,
+115,46,99,112,112,36,105,99,111,110,115,95,51,50,120,51,50,95,100,114,105,
+118,101,46,112,110,103,60,47,98,105,116,109,97,112,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
+61,34,119,120,80,97,110,101,108,34,32,110,97,109,101,61,34,80,65,78,69,
+76,95,68,82,73,86,69,83,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,115,116,121,108,101,62,119,120,84,65,66,95,84,82,65,86,69,82,
+83,65,76,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
+120,70,108,101,120,71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,114,111,119,115,62,48,60,
+47,114,111,119,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,99,111,108,115,62,49,60,47,99,111,108,115,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,103,97,112,62,48,60,47,118,
+103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,104,103,97,112,62,48,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,
+108,115,62,48,60,47,103,114,111,119,97,98,108,101,99,111,108,115,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,
+97,98,108,101,114,111,119,115,47,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,
+111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,
+102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,98,111,114,100,101,114,62,48,60,47,98,111,114,100,101,114,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,
+106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,108,101,120,71,114,
+105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,114,111,119,115,62,48,60,47,114,111,119,
+115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,99,111,108,115,62,51,60,47,99,111,108,115,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,103,97,112,62,48,
+60,47,118,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,104,103,97,112,62,48,60,47,104,103,97,112,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,
+114,111,119,97,98,108,101,99,111,108,115,62,49,60,47,103,114,111,119,97,
+98,108,101,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111,119,
+115,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,
112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
@@ -3835,58 +3915,130 @@ static unsigned char xml_res_file_26[] = {
99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,56,48,44,45,49,60,
47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,68,45,82,79,77,
-58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,
-119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
-116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,
-112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,
-68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,
-111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
-61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,
-105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,114,
-105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
-61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,
-116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,67,
-111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,67,79,
-77,66,79,95,67,68,83,80,69,69,68,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,
-121,108,101,62,119,120,67,66,95,68,82,79,80,68,79,87,78,124,119,120,67,
-66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,115,105,122,101,62,51,53,48,44,45,49,60,47,115,105,122,101,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
-99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
-99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,68,32,77,111,100,
+101,108,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,
+49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,
+122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,
+47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,
+65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,
+47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
-115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,
-62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
+115,115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+114,105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,
+114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,
+114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+119,120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,73,68,67,
+95,67,79,77,66,79,95,67,68,77,79,68,69,76,34,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+115,116,121,108,101,62,119,120,67,66,95,68,82,79,80,68,79,87,78,124,119,
+120,67,66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,115,105,122,101,62,51,53,48,44,45,49,60,47,115,105,122,
+101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
+110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
+69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
+62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,
+60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,95,
+67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,
+99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,56,48,44,45,49,60,
+47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,68,32,83,112,101,
+101,100,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,
+49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,
+122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,
+47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,
+65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,
+47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+114,105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,
+114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,
+114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+119,120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,73,68,67,
+95,67,79,77,66,79,95,67,68,83,80,69,69,68,34,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+115,116,121,108,101,62,119,120,67,66,95,68,82,79,80,68,79,87,78,124,119,
+120,67,66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,115,105,122,101,62,51,53,48,44,45,49,60,47,115,105,122,
+101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
+110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
@@ -6501,105 +6653,174 @@ static unsigned char xml_res_file_26[] = {
97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,
111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,102,108,97,103,62,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,
-69,82,84,73,67,65,76,124,119,120,65,76,76,60,47,102,108,97,103,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,
-60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,
-97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,115,105,122,101,62,56,48,44,45,49,60,47,115,105,122,101,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
-108,62,70,105,108,101,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,
-97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
-99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,
-48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,
+60,102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,
+95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,
10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
-84,101,120,116,67,116,114,108,34,32,110,97,109,101,61,34,73,68,67,95,69,
-68,73,84,67,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-115,116,121,108,101,62,119,120,84,69,95,82,69,65,68,79,78,76,89,60,47,115,
-116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-115,105,122,101,62,51,53,48,44,45,49,60,47,115,105,122,101,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,
+83,116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,108,97,98,101,108,62,73,109,97,103,101,32,70,111,
+114,109,97,116,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
+116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,
+47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,
+60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,67,111,
+109,98,111,66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,72,68,70,79,
+82,77,65,84,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+115,116,121,108,101,62,119,120,67,66,95,68,82,79,80,68,79,87,78,124,119,
+120,67,66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,101,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,51,53,
+48,44,45,49,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
+69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,
+114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,
+62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
+105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,73,
+71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,124,119,120,65,76,
+76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,56,48,
+44,45,49,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,108,97,98,101,108,62,78,101,119,32,70,105,108,101,58,60,
+47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
+119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,
+114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,119,120,84,101,120,116,67,116,114,108,34,
+32,110,97,109,101,61,34,73,68,67,95,69,68,73,84,67,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,51,53,48,44,45,
+49,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
+105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,
+60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,119,120,66,105,116,109,97,112,66,117,116,116,111,110,34,32,
+110,97,109,101,61,34,73,68,67,95,67,70,73,76,69,34,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,66,85,
+95,65,85,84,79,68,82,65,87,60,47,115,116,121,108,101,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,62,119,120,
+45,114,101,115,111,117,114,99,101,115,46,99,112,112,36,105,99,111,110,115,
+95,49,54,120,49,54,95,102,111,108,100,101,114,46,112,110,103,60,47,98,105,
+116,109,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+100,101,102,97,117,108,116,62,48,60,47,100,101,102,97,117,108,116,62,10,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
-97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,
-111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,
-47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,105,116,
-109,97,112,66,117,116,116,111,110,34,32,110,97,109,101,61,34,73,68,67,95,
-67,70,73,76,69,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,115,116,121,108,101,62,119,120,66,85,95,65,85,84,79,68,82,65,87,60,47,
-115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,98,105,116,109,97,112,62,119,120,45,114,101,115,111,117,114,99,101,
-115,46,99,112,112,36,105,99,111,110,115,95,49,54,120,49,54,95,102,111,108,
-100,101,114,46,112,110,103,60,47,98,105,116,109,97,112,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,108,116,62,48,
-60,47,100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,
-114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,
-111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,
-47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,
-111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,
-105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
-99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
-110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,
-108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
-100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
-34,119,120,70,108,101,120,71,114,105,100,83,105,122,101,114,34,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,114,111,119,115,62,48,60,
-47,114,111,119,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,99,111,108,115,62,52,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,118,103,97,112,62,48,60,47,118,103,97,112,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,103,97,112,
-62,48,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,115,47,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,
-101,114,111,119,115,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
-110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
-108,97,103,62,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,
-73,67,65,76,124,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,
-53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-119,120,83,116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,83,101,
-99,116,111,114,115,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,
-119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,
+111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
+62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,
+114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,
+105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,
+122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
+69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,
+114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,119,120,70,108,101,120,71,114,105,100,83,
+105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,114,111,119,115,62,48,60,47,114,111,119,115,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,99,111,108,115,62,52,60,47,99,111,108,
+115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,103,97,
+112,62,48,60,47,118,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,104,103,97,112,62,48,60,47,104,103,97,112,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,
+99,111,108,115,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,103,114,111,119,97,98,108,101,114,111,119,115,47,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,
+48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,73,71,78,95,67,
+69,78,84,69,82,95,86,69,82,84,73,67,65,76,124,119,120,65,76,76,60,47,102,
+108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+108,97,98,101,108,62,83,101,99,116,111,114,115,58,60,47,108,97,98,101,108,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,
+114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,
+111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,
+60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,119,120,84,101,120,116,67,116,114,
+108,34,32,110,97,109,101,61,34,73,68,67,95,69,68,73,84,49,34,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,
+101,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,
+32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,
+122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,
+111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+102,108,97,103,62,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,
+82,84,73,67,65,76,124,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
+62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,119,120,83,116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,72,
+101,97,100,115,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,
+114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,
116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,
114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
61,34,119,120,84,101,120,116,67,116,114,108,34,32,110,97,109,101,61,34,
-73,68,67,95,69,68,73,84,49,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+73,68,67,95,69,68,73,84,50,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
@@ -6614,7 +6835,346 @@ static unsigned char xml_res_file_26[] = {
101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,
105,99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,108,97,98,101,108,62,72,101,97,100,115,58,60,47,108,
+32,32,32,32,32,32,60,108,97,98,101,108,62,67,121,108,105,110,100,101,114,
+115,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
+106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
+114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
+108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,
+60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
+120,84,101,120,116,67,116,114,108,34,32,110,97,109,101,61,34,73,68,67,95,
+69,68,73,84,51,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
+110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,73,71,78,
+95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,124,119,120,65,76,76,60,
+47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,
+116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,108,97,98,101,108,62,83,105,122,101,32,40,77,66,41,58,60,47,108,97,98,
+101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
+116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,
+116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,
+76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,124,119,120,
+65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
+101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,84,101,120,116,
+67,116,114,108,34,32,110,97,109,101,61,34,73,68,67,95,69,68,73,84,52,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,
+97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,112,
+97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,
+65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,
+60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
+98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
+110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,
+65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,
+108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,119,120,83,116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,84,121,112,101,
+58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
+61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,
+105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,
+97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,
+100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,119,120,67,111,109,98,111,66,111,
+120,34,32,110,97,109,101,61,34,73,68,67,95,72,68,84,89,80,69,34,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,
+119,120,67,66,95,68,82,79,80,68,79,87,78,124,119,120,67,66,95,82,69,65,
+68,79,78,76,89,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,115,105,122,101,62,51,53,48,44,45,49,60,47,115,
+105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,
+97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,
+114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,
+111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,
+47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,
+111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,
+105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
+110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,
+65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,
+108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,110,97,109,101,61,
+34,73,68,67,95,72,68,66,76,79,67,75,83,73,90,69,76,65,66,69,76,34,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,
+66,108,111,99,107,32,115,105,122,101,58,60,47,108,97,98,101,108,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,
+60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,
+101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,
+105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,
+108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,119,120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,73,68,
+67,95,72,68,66,76,79,67,75,83,73,90,69,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,67,66,95,68,82,
+79,80,68,79,87,78,124,119,120,67,66,95,82,69,65,68,79,78,76,89,60,47,115,
+116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+115,105,122,101,62,51,53,48,44,45,49,60,47,115,105,122,101,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,
+116,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
+99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
+32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,
+116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
+108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,
+47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
+32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,
+106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,
+109,34,62,10,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,
+49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,60,
+102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,
+32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,
+111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,122,101,114,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,105,101,110,116,
+62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,114,105,101,110,116,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,
+105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,
+97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,
+98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
+119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,
+114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,119,120,66,117,116,116,111,110,34,32,110,
+97,109,101,61,34,119,120,73,68,95,79,75,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,79,75,60,47,108,97,98,101,
+108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,
+97,117,108,116,62,49,60,47,100,101,102,97,117,108,116,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,
+111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
+62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
+101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,119,120,66,117,116,116,111,110,34,32,
+110,97,109,101,61,34,119,120,73,68,95,67,65,78,67,69,76,34,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,97,
+110,99,101,108,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,100,101,102,97,117,108,116,62,48,60,47,100,101,
+102,97,117,108,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
+98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,68,105,97,
+108,111,103,34,32,110,97,109,101,61,34,72,100,83,105,122,101,68,108,103,
+34,62,10,32,32,32,32,60,116,105,116,108,101,62,72,97,114,100,32,68,105,
+115,99,32,80,97,114,97,109,101,116,101,114,115,60,47,116,105,116,108,101,
+62,10,32,32,32,32,60,99,101,110,116,101,114,101,100,62,49,60,47,99,101,
+110,116,101,114,101,100,62,10,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,119,120,80,97,110,101,108,34,32,110,97,109,101,61,
+34,82,79,79,84,95,80,65,78,69,76,34,62,10,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,119,120,70,108,101,120,71,114,105,
+100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,60,114,111,119,
+115,62,48,60,47,114,111,119,115,62,10,32,32,32,32,32,32,32,32,60,99,111,
+108,115,62,49,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,60,118,
+103,97,112,62,48,60,47,118,103,97,112,62,10,32,32,32,32,32,32,32,32,60,
+104,103,97,112,62,48,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,32,
+60,103,114,111,119,97,98,108,101,99,111,108,115,47,62,10,32,32,32,32,32,
+32,32,32,60,103,114,111,119,97,98,108,101,114,111,119,115,47,62,10,32,32,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
+60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,
+32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,32,124,
+32,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,
+76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
+83,116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,60,108,97,98,101,108,62,73,110,105,116,105,97,108,32,115,101,116,
+116,105,110,103,115,32,97,114,101,32,98,97,115,101,100,32,111,110,32,102,
+105,108,101,32,115,105,122,101,60,47,108,97,98,101,108,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,
+62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
+114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,60,111,112,116,
+105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,
+32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,
+97,103,62,10,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,
+53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,60,
+111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,108,101,120,
+71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,60,114,111,119,115,62,48,60,47,114,111,119,115,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,60,99,111,108,115,62,51,60,47,99,111,108,115,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,60,118,103,97,112,62,48,60,47,118,
+103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,104,103,97,112,
+62,48,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,
+103,114,111,119,97,98,108,101,99,111,108,115,62,49,60,47,103,114,111,119,
+97,98,108,101,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+60,103,114,111,119,97,98,108,101,114,111,119,115,47,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,
+88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,
+44,48,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,
+47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,
+101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,
+105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,
+60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,119,120,70,108,101,120,71,114,105,100,83,105,122,101,114,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,114,111,119,
+115,62,48,60,47,114,111,119,115,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,99,111,108,115,62,52,60,47,99,111,108,115,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,103,97,112,62,48,60,47,
+118,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+104,103,97,112,62,48,60,47,104,103,97,112,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,115,
+47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,114,111,
+119,97,98,108,101,114,111,119,115,47,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,
+116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,102,108,97,103,62,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,
+86,69,82,84,73,67,65,76,124,119,120,65,76,76,60,47,102,108,97,103,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,
+101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
+115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
+62,83,101,99,116,111,114,115,58,60,47,108,97,98,101,108,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,
+45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,
+48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,
+97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,
+111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,119,120,84,101,120,116,67,116,114,108,34,32,110,97,
+109,101,61,34,73,68,67,95,69,68,73,84,49,34,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
+99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
+98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
+105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,
+103,62,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,
+65,76,124,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,
+47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
+120,83,116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,72,101,97,100,
+115,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
+106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
+114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
+108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,
+60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
+120,84,101,120,116,67,116,114,108,34,32,110,97,109,101,61,34,73,68,67,95,
+69,68,73,84,50,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
+110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,73,71,78,
+95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,124,119,120,65,76,76,60,
+47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,
+116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,108,97,98,101,108,62,67,121,108,105,110,100,101,114,115,58,60,47,108,
97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
@@ -6628,7 +7188,7 @@ static unsigned char xml_res_file_26[] = {
32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,
114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,84,101,120,
-116,67,116,114,108,34,32,110,97,109,101,61,34,73,68,67,95,69,68,73,84,50,
+116,67,116,114,108,34,32,110,97,109,101,61,34,73,68,67,95,69,68,73,84,51,
34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
118,97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
@@ -6644,99 +7204,91 @@ static unsigned char xml_res_file_26[] = {
32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,62,10,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
-108,62,67,121,108,105,110,100,101,114,115,58,60,47,108,97,98,101,108,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,
-97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
-110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,
-102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
-116,32,99,108,97,115,115,61,34,119,120,84,101,120,116,67,116,114,108,34,
-32,110,97,109,101,61,34,73,68,67,95,69,68,73,84,51,34,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
-110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
-108,97,103,62,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,
-73,67,65,76,124,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,
-53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-119,120,83,116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,83,105,
-122,101,32,40,77,66,41,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,
-60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
-61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,
+108,62,83,105,122,101,58,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,
+47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,
+112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,102,108,97,103,62,119,120,65,76,73,71,78,95,67,69,78,84,69,
+82,95,86,69,82,84,73,67,65,76,124,119,120,65,76,76,60,47,102,108,97,103,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,110,
+97,109,101,61,34,73,68,67,95,84,69,88,84,49,34,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,48,109,
+98,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+98,106,101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,
+62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,
+97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,
+101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,
111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,102,108,97,103,62,119,120,65,76,73,71,78,95,67,69,78,84,
-69,82,95,86,69,82,84,73,67,65,76,124,119,120,65,76,76,60,47,102,108,97,
-103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,
-114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
-97,115,115,61,34,119,120,84,101,120,116,67,116,114,108,34,32,110,97,109,
-101,61,34,73,68,67,95,69,68,73,84,52,34,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
-99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,
-47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
+60,102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,
+95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
-115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,
-112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-102,108,97,103,62,119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,95,
-67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,
-53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,
-116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,108,97,98,101,108,62,84,121,112,101,58,60,47,108,97,
-98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,
-114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
+83,116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,108,97,98,101,108,62,84,121,112,101,58,60,47,108,
+97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,
-122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
-65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,119,120,67,111,109,98,111,66,111,120,34,32,110,97,
-109,101,61,34,73,68,67,95,72,68,84,89,80,69,34,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,67,66,95,
-68,82,79,80,68,79,87,78,124,119,120,67,66,95,82,69,65,68,79,78,76,89,60,
-47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,115,105,122,101,62,51,53,48,44,45,49,60,47,115,105,122,101,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,
-47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,
-116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
-111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
-98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
+105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
+119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,
+114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,119,120,67,111,109,98,111,66,111,120,34,
+32,110,97,109,101,61,34,73,68,67,95,72,68,84,89,80,69,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,
+67,66,95,68,82,79,80,68,79,87,78,124,119,120,67,66,95,82,69,65,68,79,78,
+76,89,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,115,105,122,101,62,51,53,48,44,45,49,60,47,115,105,122,
+101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,
+117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,
+111,110,116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,
+111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
+110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,
+108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,
+101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
+62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
+114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,60,111,112,116,
+105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,
+32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,
+97,103,62,10,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,
+53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,60,
+111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,
+105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,
+105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,114,
+105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,
60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
@@ -6745,26 +7297,6 @@ static unsigned char xml_res_file_26[] = {
62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,
32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
-32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,
-116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
-110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
-32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,
-62,10,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,
-47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,
-106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,122,
-101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,105,101,
-110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,114,105,101,
-110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
-116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,
-111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
-62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,
@@ -6798,642 +7330,388 @@ static unsigned char xml_res_file_26[] = {
98,106,101,99,116,62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
10,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,
101,99,116,62,10,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
-34,119,120,68,105,97,108,111,103,34,32,110,97,109,101,61,34,72,100,83,105,
-122,101,68,108,103,34,62,10,32,32,32,32,60,116,105,116,108,101,62,72,97,
-114,100,32,68,105,115,99,32,80,97,114,97,109,101,116,101,114,115,60,47,
+34,119,120,68,105,97,108,111,103,34,32,110,97,109,101,61,34,67,111,110,
+102,105,103,117,114,101,83,101,108,101,99,116,105,111,110,68,108,103,34,
+62,10,32,32,32,32,60,116,105,116,108,101,62,80,67,101,109,32,67,111,110,
+102,105,103,117,114,97,116,105,111,110,32,77,97,110,97,103,101,114,60,47,
116,105,116,108,101,62,10,32,32,32,32,60,99,101,110,116,101,114,101,100,
62,49,60,47,99,101,110,116,101,114,101,100,62,10,32,32,32,32,60,111,98,
-106,101,99,116,32,99,108,97,115,115,61,34,119,120,80,97,110,101,108,34,
-32,110,97,109,101,61,34,82,79,79,84,95,80,65,78,69,76,34,62,10,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,
-108,101,120,71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,
-32,32,60,114,111,119,115,62,48,60,47,114,111,119,115,62,10,32,32,32,32,
-32,32,32,32,60,99,111,108,115,62,49,60,47,99,111,108,115,62,10,32,32,32,
-32,32,32,32,32,60,118,103,97,112,62,48,60,47,118,103,97,112,62,10,32,32,
-32,32,32,32,32,32,60,104,103,97,112,62,48,60,47,104,103,97,112,62,10,32,
-32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,115,47,
-62,10,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111,
-119,115,47,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,
-32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,
-116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
-119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,95,67,69,78,84,69,82,
-95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,
-32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,
-62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
-97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,73,110,105,116,
-105,97,108,32,115,101,116,116,105,110,103,115,32,97,114,101,32,98,97,115,
-101,100,32,111,110,32,102,105,108,101,32,115,105,122,101,60,47,108,97,98,
-101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,
-45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,
-98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
-116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
-115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
-32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,
-111,110,62,10,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
-69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
-32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,
-32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
-61,34,119,120,70,108,101,120,71,114,105,100,83,105,122,101,114,34,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,60,114,111,119,115,62,48,60,47,114,
-111,119,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,115,
-62,51,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,
-118,103,97,112,62,48,60,47,118,103,97,112,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,60,104,103,97,112,62,48,60,47,104,103,97,112,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,
-115,62,49,60,47,103,114,111,119,97,98,108,101,99,111,108,115,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111,
-119,115,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
-99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,
-47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
-62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
-115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,
-112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,
-53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,
-108,101,120,71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,114,111,119,115,62,48,60,47,114,111,119,
-115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,108,
-115,62,52,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,118,103,97,112,62,48,60,47,118,103,97,112,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,104,103,97,112,62,48,60,47,104,
-103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,103,
-114,111,119,97,98,108,101,99,111,108,115,47,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111,119,
-115,47,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,
-106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,
-109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
-112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
-65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,124,119,
-120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
-101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,
-105,99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,108,97,98,101,108,62,83,101,99,116,111,114,115,58,
-60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
-111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
-110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
-108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,
-60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,84,101,120,116,67,116,114,108,34,32,110,97,109,101,61,34,73,68,67,95,
-69,68,73,84,49,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
-110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,73,71,78,
-95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,124,119,120,65,76,76,60,
-47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
-99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,
-116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,108,97,98,101,108,62,72,101,97,100,115,58,60,47,108,97,98,101,108,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,
-97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
-110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,
-102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
-116,32,99,108,97,115,115,61,34,119,120,84,101,120,116,67,116,114,108,34,
-32,110,97,109,101,61,34,73,68,67,95,69,68,73,84,50,34,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
-110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
-108,97,103,62,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,
-73,67,65,76,124,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,
-53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-119,120,83,116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,121,
-108,105,110,100,101,114,115,58,60,47,108,97,98,101,108,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,45,
-49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,
-47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
-100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
-97,115,115,61,34,119,120,84,101,120,116,67,116,114,108,34,32,110,97,109,
-101,61,34,73,68,67,95,69,68,73,84,51,34,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
-98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,
-101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
-119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,73,67,65,76,
-124,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,
-111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,
-116,97,116,105,99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,83,105,122,101,58,
-60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
-111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
-114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
-110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
-108,97,103,62,119,120,65,76,73,71,78,95,67,69,78,84,69,82,95,86,69,82,84,
-73,67,65,76,124,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,
-53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-119,120,83,116,97,116,105,99,84,101,120,116,34,32,110,97,109,101,61,34,
-73,68,67,95,84,69,88,84,49,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,48,109,98,60,47,108,97,
-98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,119,114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
-99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
-99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,
-116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
-108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,
-47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
-34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,
-111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
-62,119,120,65,76,76,32,124,32,119,120,65,76,73,71,78,95,67,69,78,84,69,
-82,95,86,69,82,84,73,67,65,76,60,47,102,108,97,103,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,
-114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
-98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,
-99,84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,108,97,98,101,108,62,84,121,112,101,58,60,47,108,97,98,101,108,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,114,97,112,62,
-45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,
-116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,
-116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,
-102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,
-114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
-61,34,119,120,67,111,109,98,111,66,111,120,34,32,110,97,109,101,61,34,73,
-68,67,95,72,68,84,89,80,69,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,115,116,121,108,101,62,119,120,67,66,95,68,82,79,80,68,79,
-87,78,124,119,120,67,66,95,82,69,65,68,79,78,76,89,60,47,115,116,121,108,
-101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,
-101,62,51,53,48,44,45,49,60,47,115,105,122,101,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,118,97,108,117,101,47,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,116,47,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
-97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,
-111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
-62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,
-114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,
-105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
-32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,47,111,
-98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,
-32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,
-112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
-62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,
-32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,
-114,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,60,111,114,105,101,110,116,62,119,120,
-72,79,82,73,90,79,78,84,65,76,60,47,111,114,105,101,110,116,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,
-110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
-119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,
-100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,
-122,101,62,48,44,48,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,
-101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
-65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,119,120,66,117,116,116,111,110,34,32,110,97,109,101,
-61,34,119,120,73,68,95,79,75,34,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,108,97,98,101,108,62,79,75,60,47,108,97,98,101,108,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,
-108,116,62,49,60,47,100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
-105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,
-110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
-119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,
-114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
-116,32,99,108,97,115,115,61,34,119,120,66,117,116,116,111,110,34,32,110,
-97,109,101,61,34,119,120,73,68,95,67,65,78,67,69,76,34,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,97,110,99,
-101,108,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,100,101,102,97,117,108,116,62,48,60,47,100,101,102,97,
-117,108,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
-116,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,60,47,111,
-98,106,101,99,116,62,10,32,32,60,47,111,98,106,101,99,116,62,10,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,68,105,97,108,
-111,103,34,32,110,97,109,101,61,34,67,111,110,102,105,103,117,114,101,83,
-101,108,101,99,116,105,111,110,68,108,103,34,62,10,32,32,32,32,60,116,105,
-116,108,101,62,80,67,101,109,32,67,111,110,102,105,103,117,114,97,116,105,
-111,110,32,77,97,110,97,103,101,114,60,47,116,105,116,108,101,62,10,32,
-32,32,32,60,99,101,110,116,101,114,101,100,62,49,60,47,99,101,110,116,101,
-114,101,100,62,10,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,119,120,70,108,101,120,71,114,105,100,83,105,122,101,114,34,62,
-10,32,32,32,32,32,32,60,114,111,119,115,62,49,60,47,114,111,119,115,62,
-10,32,32,32,32,32,32,60,99,111,108,115,62,49,60,47,99,111,108,115,62,10,
-32,32,32,32,32,32,60,118,103,97,112,62,48,60,47,118,103,97,112,62,10,32,
-32,32,32,32,32,60,104,103,97,112,62,48,60,47,104,103,97,112,62,10,32,32,
-32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,115,62,48,60,47,
-103,114,111,119,97,98,108,101,99,111,108,115,62,10,32,32,32,32,32,32,60,
-103,114,111,119,97,98,108,101,114,111,119,115,62,48,60,47,103,114,111,119,
-97,98,108,101,114,111,119,115,62,10,32,32,32,32,32,32,60,111,98,106,101,
-99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,
-62,10,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,
-112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
-119,120,65,76,76,124,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,
-10,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,
-114,100,101,114,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,119,120,70,108,101,120,71,114,105,100,83,105,
-122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,60,114,111,119,115,62,
-50,60,47,114,111,119,115,62,10,32,32,32,32,32,32,32,32,32,32,60,99,111,
-108,115,62,50,60,47,99,111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,
-60,118,103,97,112,62,48,60,47,118,103,97,112,62,10,32,32,32,32,32,32,32,
-32,32,32,60,104,103,97,112,62,48,60,47,104,103,97,112,62,10,32,32,32,32,
-32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,99,111,108,115,62,48,
-60,47,103,114,111,119,97,98,108,101,99,111,108,115,62,10,32,32,32,32,32,
-32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111,119,115,62,48,60,
-47,103,114,111,119,97,98,108,101,114,111,119,115,62,10,32,32,32,32,32,32,
-32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,
-122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,
-65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,111,114,105,101,110,116,62,119,120,86,69,
-82,84,73,67,65,76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
-34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,
-116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-102,108,97,103,62,119,120,65,76,76,124,119,120,69,88,80,65,78,68,60,47,
-102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
-97,115,115,61,34,119,120,76,105,115,116,66,111,120,34,32,110,97,109,101,
-61,34,73,68,67,95,76,73,83,84,34,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,76,66,95,83,73,78,
-71,76,69,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,115,105,122,101,62,50,53,48,44,51,48,48,60,47,
-115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,99,111,110,116,101,110,116,47,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
-32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
-60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
-105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,
-116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,
-47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
-100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,114,105,101,110,116,62,119,120,86,69,82,84,73,67,65,
-76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,
-101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
-62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,
-100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
-98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,105,116,109,97,
-112,66,117,116,116,111,110,34,32,110,97,109,101,61,34,119,120,73,68,95,
-79,75,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-115,116,121,108,101,62,119,120,66,85,95,65,85,84,79,68,82,65,87,60,47,115,
-116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,116,111,111,108,116,105,112,62,76,111,97,100,60,47,116,111,111,108,
-116,105,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,98,105,116,109,97,112,62,119,120,45,114,101,115,111,117,114,99,101,115,
-46,99,112,112,36,105,99,111,110,115,95,51,50,120,51,50,95,99,111,110,116,
-114,111,108,95,112,108,97,121,95,98,108,117,101,46,112,110,103,60,47,98,
-105,116,109,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,100,101,102,97,117,108,116,62,49,60,47,100,101,102,97,117,108,
-116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
-98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
-98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,
-101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
-112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,
-76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
-116,32,99,108,97,115,115,61,34,119,120,66,105,116,109,97,112,66,117,116,
-116,111,110,34,32,110,97,109,101,61,34,73,68,67,95,67,79,78,70,73,71,34,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,
-121,108,101,62,119,120,66,85,95,65,85,84,79,68,82,65,87,60,47,115,116,121,
-108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-116,111,111,108,116,105,112,62,67,111,110,102,105,103,117,114,101,60,47,
-116,111,111,108,116,105,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,98,105,116,109,97,112,62,119,120,45,114,101,115,111,117,
-114,99,101,115,46,99,112,112,36,105,99,111,110,115,95,51,50,120,51,50,95,
-115,101,116,116,105,110,103,95,116,111,111,108,115,46,112,110,103,60,47,
-98,105,116,109,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,100,101,102,97,117,108,116,62,48,60,47,100,101,102,97,117,108,
-116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
-98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
-98,106,101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
-110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,
-47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,48,44,48,
-60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
-105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
-65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
-99,116,32,99,108,97,115,115,61,34,119,120,66,105,116,109,97,112,66,117,
-116,116,111,110,34,32,110,97,109,101,61,34,73,68,67,95,67,79,78,70,73,71,
-95,72,79,83,84,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,115,116,121,108,101,62,119,120,66,85,95,65,85,84,79,68,82,65,87,
-60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,116,111,111,108,116,105,112,62,67,111,110,102,105,103,
-117,114,101,32,72,111,115,116,60,47,116,111,111,108,116,105,112,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,
-112,62,119,120,45,114,101,115,111,117,114,99,101,115,46,99,112,112,36,105,
-99,111,110,115,95,51,50,120,51,50,95,119,105,100,101,115,99,114,101,101,
-110,46,112,110,103,60,47,98,105,116,109,97,112,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,108,116,62,48,
-60,47,100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
-32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,
-116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,
-105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,
-102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
-100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,114,105,101,110,116,62,119,120,72,79,82,73,90,79,78,
-84,65,76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,
+106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,108,101,120,71,114,
+105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,60,114,111,119,115,
+62,49,60,47,114,111,119,115,62,10,32,32,32,32,32,32,60,99,111,108,115,62,
+49,60,47,99,111,108,115,62,10,32,32,32,32,32,32,60,118,103,97,112,62,48,
+60,47,118,103,97,112,62,10,32,32,32,32,32,32,60,104,103,97,112,62,48,60,
+47,104,103,97,112,62,10,32,32,32,32,32,32,60,103,114,111,119,97,98,108,
+101,99,111,108,115,62,48,60,47,103,114,111,119,97,98,108,101,99,111,108,
+115,62,10,32,32,32,32,32,32,60,103,114,111,119,97,98,108,101,114,111,119,
+115,62,48,60,47,103,114,111,119,97,98,108,101,114,111,119,115,62,10,32,
32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
-105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,
-111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,
-97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,
+105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,60,111,
+112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,
+32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,124,119,120,69,88,
+80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,60,98,111,
+114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,
+32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,70,
+108,101,120,71,114,105,100,83,105,122,101,114,34,62,10,32,32,32,32,32,32,
+32,32,32,32,60,114,111,119,115,62,50,60,47,114,111,119,115,62,10,32,32,
+32,32,32,32,32,32,32,32,60,99,111,108,115,62,50,60,47,99,111,108,115,62,
+10,32,32,32,32,32,32,32,32,32,32,60,118,103,97,112,62,48,60,47,118,103,
+97,112,62,10,32,32,32,32,32,32,32,32,32,32,60,104,103,97,112,62,48,60,47,
+104,103,97,112,62,10,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,
+98,108,101,99,111,108,115,62,48,60,47,103,114,111,119,97,98,108,101,99,
+111,108,115,62,10,32,32,32,32,32,32,32,32,32,32,60,103,114,111,119,97,98,
+108,101,114,111,119,115,62,48,60,47,103,114,111,119,97,98,108,101,114,111,
+119,115,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,
+111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
+108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,
32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,
-111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,105,116,
-109,97,112,66,117,116,116,111,110,34,32,110,97,109,101,61,34,73,68,67,95,
-78,69,87,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,115,116,121,108,101,62,119,120,66,85,95,65,85,84,79,68,82,65,87,60,47,
-115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,116,111,111,108,116,105,112,62,78,101,119,60,47,116,111,111,
-108,116,105,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,98,105,116,109,97,112,62,119,120,45,114,101,115,111,117,114,99,101,
-115,46,99,112,112,36,105,99,111,110,115,95,51,50,120,51,50,95,99,111,109,
-112,117,116,101,114,95,97,100,100,46,112,110,103,60,47,98,105,116,109,97,
-112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,100,
-101,102,97,117,108,116,62,48,60,47,100,101,102,97,117,108,116,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
+111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,
+106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,122,
+101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,105,
+101,110,116,62,119,120,86,69,82,84,73,67,65,76,60,47,111,114,105,101,110,
116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,
10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
-110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,
-97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,
-114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
-115,115,61,34,119,120,66,105,116,109,97,112,66,117,116,116,111,110,34,32,
-110,97,109,101,61,34,73,68,67,95,82,69,78,65,77,69,34,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,
-120,66,85,95,65,85,84,79,68,82,65,87,60,47,115,116,121,108,101,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,116,111,111,108,116,
-105,112,62,82,101,110,97,109,101,60,47,116,111,111,108,116,105,112,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,
-97,112,62,119,120,45,114,101,115,111,117,114,99,101,115,46,99,112,112,36,
-105,99,111,110,115,95,51,50,120,51,50,95,99,111,109,112,117,116,101,114,
-95,101,100,105,116,46,112,110,103,60,47,98,105,116,109,97,112,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,
-108,116,62,48,60,47,100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
-97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,
-60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,
-101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,
+110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,124,119,120,
+69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
+101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,
+106,101,99,116,32,99,108,97,115,115,61,34,119,120,76,105,115,116,66,111,
+120,34,32,110,97,109,101,61,34,73,68,67,95,76,73,83,84,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,
+119,120,76,66,95,83,73,78,71,76,69,60,47,115,116,121,108,101,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,50,
+53,48,44,51,48,48,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,99,111,110,116,101,110,116,47,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
-34,119,120,66,105,116,109,97,112,66,117,116,116,111,110,34,32,110,97,109,
-101,61,34,73,68,67,95,67,79,80,89,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,66,85,95,65,85,
-84,79,68,82,65,87,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,116,111,111,108,116,105,112,62,67,111,
-112,121,60,47,116,111,111,108,116,105,112,62,10,32,32,32,32,32,32,32,32,
+34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,
+120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,105,101,110,116,62,119,
+120,86,69,82,84,73,67,65,76,60,47,111,114,105,101,110,116,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,
+47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,
+114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+119,120,66,105,116,109,97,112,66,117,116,116,111,110,34,32,110,97,109,101,
+61,34,119,120,73,68,95,79,75,34,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,66,85,95,65,85,84,
+79,68,82,65,87,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,116,111,111,108,116,105,112,62,76,111,
+97,100,60,47,116,111,111,108,116,105,112,62,10,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,62,119,120,45,114,
101,115,111,117,114,99,101,115,46,99,112,112,36,105,99,111,110,115,95,51,
-50,120,51,50,95,99,111,109,112,117,116,101,114,95,103,111,46,112,110,103,
-60,47,98,105,116,109,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,100,101,102,97,117,108,116,62,48,60,47,100,101,102,97,
-117,108,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
-111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,
-105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
-65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
-99,116,32,99,108,97,115,115,61,34,119,120,66,105,116,109,97,112,66,117,
-116,116,111,110,34,32,110,97,109,101,61,34,73,68,67,95,68,69,76,69,84,69,
-34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,
-121,108,101,62,119,120,66,85,95,65,85,84,79,68,82,65,87,60,47,115,116,121,
-108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-116,111,111,108,116,105,112,62,68,101,108,101,116,101,60,47,116,111,111,
-108,116,105,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,98,105,116,109,97,112,62,119,120,45,114,101,115,111,117,114,99,101,
-115,46,99,112,112,36,105,99,111,110,115,95,51,50,120,51,50,95,99,111,109,
-112,117,116,101,114,95,100,101,108,101,116,101,46,112,110,103,60,47,98,
-105,116,109,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,100,101,102,97,117,108,116,62,48,60,47,100,101,102,97,117,108,
+50,120,51,50,95,99,111,110,116,114,111,108,95,112,108,97,121,95,98,108,
+117,101,46,112,110,103,60,47,98,105,116,109,97,112,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,108,116,62,
+49,60,47,100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,
+116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,
+60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
+66,105,116,109,97,112,66,117,116,116,111,110,34,32,110,97,109,101,61,34,
+73,68,67,95,67,79,78,70,73,71,34,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,66,85,95,65,85,84,
+79,68,82,65,87,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,116,111,111,108,116,105,112,62,67,111,
+110,102,105,103,117,114,101,60,47,116,111,111,108,116,105,112,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,
+112,62,119,120,45,114,101,115,111,117,114,99,101,115,46,99,112,112,36,105,
+99,111,110,115,95,51,50,120,51,50,95,115,101,116,116,105,110,103,95,116,
+111,111,108,115,46,112,110,103,60,47,98,105,116,109,97,112,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,108,
+116,62,48,60,47,100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
+115,61,34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,
+111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,
+97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,
+60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,115,105,122,101,62,48,44,48,60,47,115,105,122,101,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,
+62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,
+103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
+115,61,34,119,120,66,105,116,109,97,112,66,117,116,116,111,110,34,32,110,
+97,109,101,61,34,73,68,67,95,67,79,78,70,73,71,95,72,79,83,84,34,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,
+101,62,119,120,66,85,95,65,85,84,79,68,82,65,87,60,47,115,116,121,108,101,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,116,111,
+111,108,116,105,112,62,67,111,110,102,105,103,117,114,101,32,72,111,115,
+116,60,47,116,111,111,108,116,105,112,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,62,119,120,45,114,101,
+115,111,117,114,99,101,115,46,99,112,112,36,105,99,111,110,115,95,51,50,
+120,51,50,95,119,105,100,101,115,99,114,101,101,110,46,112,110,103,60,47,
+98,105,116,109,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,100,101,102,97,117,108,116,62,48,60,47,100,101,102,97,117,108,
116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,
+32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,
111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
-108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,
-32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
-101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
-116,32,99,108,97,115,115,61,34,119,120,66,105,116,109,97,112,66,117,116,
-116,111,110,34,32,110,97,109,101,61,34,119,120,73,68,95,67,65,78,67,69,
-76,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,
-101,62,119,120,66,85,95,65,85,84,79,68,82,65,87,60,47,115,116,121,108,101,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,116,111,111,108,116,
-105,112,62,81,117,105,116,60,47,116,111,111,108,116,105,112,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,62,119,120,
-45,114,101,115,111,117,114,99,101,115,46,99,112,112,36,105,99,111,110,115,
-95,51,50,120,51,50,95,100,111,111,114,95,105,110,46,112,110,103,60,47,98,
-105,116,109,97,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,100,
-101,102,97,117,108,116,62,48,60,47,100,101,102,97,117,108,116,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
-32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
-32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,60,47,111,
-98,106,101,99,116,62,10,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,60,47,111,98,106,101,99,116,62,10,32,32,60,111,98,106,101,99,116,32,
-99,108,97,115,115,61,34,119,120,68,105,97,108,111,103,34,32,110,97,109,
-101,61,34,83,104,97,100,101,114,77,97,110,97,103,101,114,68,108,103,34,
-62,10,32,32,32,32,60,115,116,121,108,101,62,119,120,68,69,70,65,85,76,84,
-95,68,73,65,76,79,71,95,83,84,89,76,69,124,119,120,83,84,65,89,95,79,78,
-95,84,79,80,60,47,115,116,121,108,101,62,10,32,32,32,32,60,116,105,116,
-108,101,62,80,67,101,109,32,83,104,97,100,101,114,32,77,97,110,97,103,101,
-114,60,47,116,105,116,108,101,62,10,32,32,32,32,60,99,101,110,116,101,114,
-101,100,62,49,60,47,99,101,110,116,101,114,101,100,62,10,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,80,97,110,101,
-108,34,32,110,97,109,101,61,34,82,79,79,84,95,80,65,78,69,76,34,62,10,32,
-32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
-120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,60,111,
-98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,
-101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,
-120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,60,
-98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,
-32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
-119,120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,114,105,101,110,116,62,119,120,72,79,82,73,90,79,78,
-84,65,76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,
-101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,48,
-60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,76,105,
-115,116,66,111,120,34,32,110,97,109,101,61,34,73,68,67,95,76,73,83,84,34,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,
-101,62,119,120,76,66,95,83,73,78,71,76,69,60,47,115,116,121,108,101,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,105,122,101,62,
-51,48,48,44,51,53,48,60,47,115,105,122,101,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
+108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,
+111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,
+106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,122,
+101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,105,
+101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,114,105,
+101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
+101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,
+105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,
+47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,119,120,66,105,116,109,97,112,66,117,116,116,111,110,
+34,32,110,97,109,101,61,34,73,68,67,95,78,69,87,34,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,
+66,85,95,65,85,84,79,68,82,65,87,60,47,115,116,121,108,101,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,116,111,111,108,116,
+105,112,62,78,101,119,60,47,116,111,111,108,116,105,112,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,62,
+119,120,45,114,101,115,111,117,114,99,101,115,46,99,112,112,36,105,99,111,
+110,115,95,51,50,120,51,50,95,99,111,109,112,117,116,101,114,95,97,100,
+100,46,112,110,103,60,47,98,105,116,109,97,112,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,108,116,62,48,
+60,47,100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,
-122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,
-62,48,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
-66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,60,111,114,105,101,110,116,62,119,120,86,69,82,84,73,67,
-65,76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,
-105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,
-108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,98,111,114,100,101,114,62,48,60,47,98,111,114,100,101,114,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,119,120,66,117,116,116,111,110,34,32,110,97,
-109,101,61,34,73,68,67,95,65,68,68,34,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,65,100,100,60,
-47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
-61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,
-60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,98,111,114,100,101,114,62,48,60,47,98,111,114,100,101,114,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,119,120,66,117,116,116,111,110,34,
-32,110,97,109,101,61,34,73,68,67,95,82,69,77,79,86,69,34,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,
-62,82,101,109,111,118,101,60,47,108,97,98,101,108,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,
+115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,
+105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
+108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,
+98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,105,
+116,109,97,112,66,117,116,116,111,110,34,32,110,97,109,101,61,34,73,68,
+67,95,82,69,78,65,77,69,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,115,116,121,108,101,62,119,120,66,85,95,65,85,84,79,68,
+82,65,87,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,116,111,111,108,116,105,112,62,82,101,110,97,
+109,101,60,47,116,111,111,108,116,105,112,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,62,119,120,45,114,
+101,115,111,117,114,99,101,115,46,99,112,112,36,105,99,111,110,115,95,51,
+50,120,51,50,95,99,111,109,112,117,116,101,114,95,101,100,105,116,46,112,
+110,103,60,47,98,105,116,109,97,112,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,100,101,102,97,117,108,116,62,48,60,47,100,101,
+102,97,117,108,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
+114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
+119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,
+101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,
+106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,105,116,109,97,112,
+66,117,116,116,111,110,34,32,110,97,109,101,61,34,73,68,67,95,67,79,80,
+89,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,115,
+116,121,108,101,62,119,120,66,85,95,65,85,84,79,68,82,65,87,60,47,115,116,
+121,108,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,116,111,111,108,116,105,112,62,67,111,112,121,60,47,116,111,111,108,
+116,105,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,98,105,116,109,97,112,62,119,120,45,114,101,115,111,117,114,99,101,115,
+46,99,112,112,36,105,99,111,110,115,95,51,50,120,51,50,95,99,111,109,112,
+117,116,101,114,95,103,111,46,112,110,103,60,47,98,105,116,109,97,112,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,
+97,117,108,116,62,48,60,47,100,101,102,97,117,108,116,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
+108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,
+48,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,
+101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,119,120,66,105,116,109,97,112,66,117,116,116,111,110,34,32,110,97,109,
+101,61,34,73,68,67,95,68,69,76,69,84,69,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,66,85,95,
+65,85,84,79,68,82,65,87,60,47,115,116,121,108,101,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,116,111,111,108,116,105,112,62,
+68,101,108,101,116,101,60,47,116,111,111,108,116,105,112,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,97,112,62,
+119,120,45,114,101,115,111,117,114,99,101,115,46,99,112,112,36,105,99,111,
+110,115,95,51,50,120,51,50,95,99,111,109,112,117,116,101,114,95,100,101,
+108,101,116,101,46,112,110,103,60,47,98,105,116,109,97,112,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,108,
+116,62,48,60,47,100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
+32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
+114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
+112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,
+102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
+120,66,105,116,109,97,112,66,117,116,116,111,110,34,32,110,97,109,101,61,
+34,119,120,73,68,95,67,65,78,67,69,76,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,66,85,95,65,85,84,79,
+68,82,65,87,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,116,111,111,108,116,105,112,62,81,117,105,116,60,47,116,
+111,111,108,116,105,112,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,98,105,116,109,97,112,62,119,120,45,114,101,115,111,117,114,99,101,115,
+46,99,112,112,36,105,99,111,110,115,95,51,50,120,51,50,95,100,111,111,114,
+95,105,110,46,112,110,103,60,47,98,105,116,109,97,112,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,108,116,62,48,60,47,
+100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,
+47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,
+98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
+116,62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
+32,60,47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101,99,116,
+62,10,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
+68,105,97,108,111,103,34,32,110,97,109,101,61,34,83,104,97,100,101,114,
+77,97,110,97,103,101,114,68,108,103,34,62,10,32,32,32,32,60,115,116,121,
+108,101,62,119,120,68,69,70,65,85,76,84,95,68,73,65,76,79,71,95,83,84,89,
+76,69,124,119,120,83,84,65,89,95,79,78,95,84,79,80,60,47,115,116,121,108,
+101,62,10,32,32,32,32,60,116,105,116,108,101,62,80,67,101,109,32,83,104,
+97,100,101,114,32,77,97,110,97,103,101,114,60,47,116,105,116,108,101,62,
+10,32,32,32,32,60,99,101,110,116,101,114,101,100,62,49,60,47,99,101,110,
+116,101,114,101,100,62,10,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,119,120,80,97,110,101,108,34,32,110,97,109,101,61,34,82,
+79,79,84,95,80,65,78,69,76,34,62,10,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,122,101,114,
+34,62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
+32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,
+103,62,10,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,53,
+60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,60,111,
+98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,
+122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,105,
+101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,76,60,47,111,114,105,
+101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,
+120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,60,98,111,114,100,101,114,62,48,60,47,98,111,114,100,101,114,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
+99,108,97,115,115,61,34,119,120,76,105,115,116,66,111,120,34,32,110,97,
+109,101,61,34,73,68,67,95,76,73,83,84,34,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,115,116,121,108,101,62,119,120,76,66,95,83,73,
+78,71,76,69,60,47,115,116,121,108,101,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,60,115,105,122,101,62,51,48,48,44,51,53,48,60,47,115,
+105,122,101,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
+106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,
+120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,98,111,114,100,101,114,62,48,60,47,98,111,114,100,
+101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,122,101,114,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,114,105,
+101,110,116,62,119,120,86,69,82,84,73,67,65,76,60,47,111,114,105,101,110,
116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
+101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,
+34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,
+97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,48,60,
+47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
+120,66,117,116,116,111,110,34,32,110,97,109,101,61,34,73,68,67,95,65,68,
+68,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,108,97,98,101,108,62,65,100,100,60,47,108,97,98,101,108,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
+116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
+106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,
+116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,
+114,62,48,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
+61,34,119,120,66,117,116,116,111,110,34,32,110,97,109,101,61,34,73,68,67,
+95,82,69,77,79,86,69,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,108,97,98,101,108,62,82,101,109,111,118,101,60,47,
+108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,115,112,97,99,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,
+110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
+108,97,103,62,119,120,69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,
+10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,
+103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,48,60,47,
+98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,
+66,117,116,116,111,110,34,32,110,97,109,101,61,34,73,68,67,95,67,79,78,
+70,73,71,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,60,108,97,98,101,108,62,67,111,110,102,105,103,117,114,101,46,46,
+46,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
+115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
+65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,60,98,111,114,100,101,114,62,48,60,47,98,111,114,100,
+101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,117,116,116,
+111,110,34,32,110,97,109,101,61,34,73,68,67,95,77,79,86,69,95,85,80,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,
+97,98,101,108,62,77,111,118,101,32,117,112,60,47,108,97,98,101,108,62,10,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
+114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,
+100,101,114,62,48,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,119,120,66,117,116,116,111,110,34,32,110,97,109,101,61,
+34,73,68,67,95,77,79,86,69,95,68,79,87,78,34,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,77,111,118,
+101,32,100,111,119,110,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,
+99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,114,34,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,
110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,65,78,
68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
@@ -7445,135 +7723,91 @@ static unsigned char xml_res_file_26[] = {
60,98,111,114,100,101,114,62,48,60,47,98,111,114,100,101,114,62,10,32,32,
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
32,99,108,97,115,115,61,34,119,120,66,117,116,116,111,110,34,32,110,97,
-109,101,61,34,73,68,67,95,67,79,78,70,73,71,34,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,67,111,
-110,102,105,103,117,114,101,46,46,46,60,47,108,97,98,101,108,62,10,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,
-116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,114,105,
-116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,102,108,97,103,62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,
-114,62,48,60,47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,
-61,34,119,120,66,117,116,116,111,110,34,32,110,97,109,101,61,34,73,68,67,
-95,77,79,86,69,95,85,80,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,108,97,98,101,108,62,77,111,118,101,32,117,112,
-60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,
+109,101,61,34,73,68,67,95,65,80,80,76,89,34,62,10,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,65,112,112,
+108,121,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,
-76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,98,111,114,100,101,114,62,48,60,47,98,111,114,100,101,114,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,119,120,66,117,116,116,111,110,34,
-32,110,97,109,101,61,34,73,68,67,95,77,79,86,69,95,68,79,87,78,34,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,
-101,108,62,77,111,118,101,32,100,111,119,110,60,47,108,97,98,101,108,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
-111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,112,97,99,101,
-114,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,
-112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
-69,88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,76,
-76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,32,60,98,111,114,100,101,114,62,48,60,47,98,111,114,100,101,114,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,119,120,66,117,116,116,111,110,34,
-32,110,97,109,101,61,34,73,68,67,95,65,80,80,76,89,34,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,108,62,
-65,112,112,108,121,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,
-32,99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,
-62,119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,48,60,47,98,
-111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,
-117,116,116,111,110,34,32,110,97,109,101,61,34,119,120,73,68,95,79,75,34,
-62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,
-97,98,101,108,62,79,75,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,108,116,
-62,49,60,47,100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,
-99,108,97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,
-119,120,65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,
-32,32,32,32,32,32,32,32,32,60,98,111,114,100,101,114,62,48,60,47,98,111,
-114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,117,116,
-116,111,110,34,32,110,97,109,101,61,34,119,120,73,68,95,67,65,78,67,69,
-76,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
-60,108,97,98,101,108,62,67,97,110,99,101,108,60,47,108,97,98,101,108,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
-101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
-111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
-111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,
-106,101,99,116,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,
-62,10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,60,
-47,111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101,99,116,62,10,
-32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,68,105,
-97,108,111,103,34,32,110,97,109,101,61,34,67,111,110,102,105,114,109,82,
-101,109,101,109,98,101,114,68,108,103,34,62,10,32,32,32,32,60,115,116,121,
-108,101,62,119,120,68,69,70,65,85,76,84,95,68,73,65,76,79,71,95,83,84,89,
-76,69,124,119,120,83,84,65,89,95,79,78,95,84,79,80,60,47,115,116,121,108,
-101,62,10,32,32,32,32,60,116,105,116,108,101,62,80,67,101,109,60,47,116,
-105,116,108,101,62,10,32,32,32,32,60,99,101,110,116,101,114,101,100,62,
-49,60,47,99,101,110,116,101,114,101,100,62,10,32,32,32,32,60,111,98,106,
-101,99,116,32,99,108,97,115,115,61,34,119,120,80,97,110,101,108,34,32,110,
-97,109,101,61,34,82,79,79,84,95,80,65,78,69,76,34,62,10,32,32,32,32,32,
-32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,
-83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,60,111,114,105,101,
-110,116,62,119,120,86,69,82,84,73,67,65,76,60,47,111,114,105,101,110,116,
-62,10,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
-115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,
-32,32,32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,
-110,62,10,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,
-88,80,65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,
-60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,
-32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
-34,119,120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,
-32,32,32,32,32,60,111,114,105,101,110,116,62,119,120,72,79,82,73,90,79,
-78,84,65,76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,
-32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,
-122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,
-10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,119,120,83,116,97,116,105,99,66,105,116,109,97,112,
-34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,
-109,97,112,32,115,116,111,99,107,95,105,100,61,34,119,120,65,82,84,95,81,
-85,69,83,84,73,79,78,34,32,115,116,111,99,107,95,99,108,105,101,110,116,
-61,34,119,120,65,82,84,95,67,77,78,95,68,73,65,76,79,71,34,47,62,10,32,
-32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,32,32,32,32,32,60,98,111,114,100,101,114,62,48,60,47,98,111,114,100,
+101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,117,116,116,
+111,110,34,32,110,97,109,101,61,34,119,120,73,68,95,79,75,34,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
+108,62,79,75,60,47,108,97,98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,32,32,60,100,101,102,97,117,108,116,62,49,60,47,
+100,101,102,97,117,108,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,32,
32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,
115,115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,
-32,32,32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,
-112,116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
-102,108,97,103,62,119,120,65,76,73,71,78,95,67,69,78,84,69,82,124,119,120,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,
65,76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,
-32,32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,
-32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,
-108,97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,
-110,97,109,101,61,34,73,68,67,95,67,79,78,70,73,82,77,95,76,65,66,69,76,
-34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
+32,32,32,32,32,32,60,98,111,114,100,101,114,62,48,60,47,98,111,114,100,
+101,114,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,
+111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,117,116,116,
+111,110,34,32,110,97,109,101,61,34,119,120,73,68,95,67,65,78,67,69,76,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,
+97,98,101,108,62,67,97,110,99,101,108,60,47,108,97,98,101,108,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,
+99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
+98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,
+98,106,101,99,116,62,10,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,
+101,99,116,62,10,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,
+10,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,32,32,60,47,
+111,98,106,101,99,116,62,10,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,68,105,97,
+108,111,103,34,32,110,97,109,101,61,34,67,111,110,102,105,114,109,82,101,
+109,101,109,98,101,114,68,108,103,34,62,10,32,32,32,32,60,115,116,121,108,
+101,62,119,120,68,69,70,65,85,76,84,95,68,73,65,76,79,71,95,83,84,89,76,
+69,124,119,120,83,84,65,89,95,79,78,95,84,79,80,60,47,115,116,121,108,101,
+62,10,32,32,32,32,60,116,105,116,108,101,62,80,67,101,109,60,47,116,105,
+116,108,101,62,10,32,32,32,32,60,99,101,110,116,101,114,101,100,62,49,60,
+47,99,101,110,116,101,114,101,100,62,10,32,32,32,32,60,111,98,106,101,99,
+116,32,99,108,97,115,115,61,34,119,120,80,97,110,101,108,34,32,110,97,109,
+101,61,34,82,79,79,84,95,80,65,78,69,76,34,62,10,32,32,32,32,32,32,60,111,
+98,106,101,99,116,32,99,108,97,115,115,61,34,119,120,66,111,120,83,105,
+122,101,114,34,62,10,32,32,32,32,32,32,32,32,60,111,114,105,101,110,116,
+62,119,120,86,69,82,84,73,67,65,76,60,47,111,114,105,101,110,116,62,10,
+32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,
+34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,
+32,32,60,111,112,116,105,111,110,62,49,60,47,111,112,116,105,111,110,62,
+10,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,69,88,80,
+65,78,68,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,60,98,
+111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,32,32,32,
+32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,119,
+120,66,111,120,83,105,122,101,114,34,62,10,32,32,32,32,32,32,32,32,32,32,
+32,32,60,111,114,105,101,110,116,62,119,120,72,79,82,73,90,79,78,84,65,
+76,60,47,111,114,105,101,110,116,62,10,32,32,32,32,32,32,32,32,32,32,32,
+32,60,111,98,106,101,99,116,32,99,108,97,115,115,61,34,115,105,122,101,
+114,105,116,101,109,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
+60,111,112,116,105,111,110,62,48,60,47,111,112,116,105,111,110,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,108,97,103,62,119,120,65,
+76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,119,120,83,116,97,116,105,99,66,105,116,109,97,112,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,98,105,116,109,
+97,112,32,115,116,111,99,107,95,105,100,61,34,119,120,65,82,84,95,81,85,
+69,83,84,73,79,78,34,32,115,116,111,99,107,95,99,108,105,101,110,116,61,
+34,119,120,65,82,84,95,67,77,78,95,68,73,65,76,79,71,34,47,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,60,47,111,98,106,101,99,116,62,10,32,32,
+32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,97,115,
+115,61,34,115,105,122,101,114,105,116,101,109,34,62,10,32,32,32,32,32,32,
+32,32,32,32,32,32,32,32,60,111,112,116,105,111,110,62,48,60,47,111,112,
+116,105,111,110,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,102,
+108,97,103,62,119,120,65,76,73,71,78,95,67,69,78,84,69,82,124,119,120,65,
+76,76,60,47,102,108,97,103,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,
+32,60,98,111,114,100,101,114,62,53,60,47,98,111,114,100,101,114,62,10,32,
+32,32,32,32,32,32,32,32,32,32,32,32,32,60,111,98,106,101,99,116,32,99,108,
+97,115,115,61,34,119,120,83,116,97,116,105,99,84,101,120,116,34,32,110,
+97,109,101,61,34,73,68,67,95,67,79,78,70,73,82,77,95,76,65,66,69,76,34,
+62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,101,
108,62,73,68,67,95,67,79,78,70,73,82,77,95,76,65,66,69,76,60,47,108,97,
98,101,108,62,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,60,119,
114,97,112,62,45,49,60,47,119,114,97,112,62,10,32,32,32,32,32,32,32,32,
@@ -7776,7 +8010,7 @@ static unsigned char xml_res_file_26[] = {
47,98,111,114,100,101,114,62,10,32,32,32,32,32,32,32,32,32,32,60,111,98,
106,101,99,116,32,99,108,97,115,115,61,34,119,120,83,116,97,116,105,99,
84,101,120,116,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32,60,108,97,98,
-101,108,62,80,67,101,109,32,118,49,52,92,110,104,116,116,112,115,58,47,
+101,108,62,80,67,101,109,32,118,49,55,92,110,104,116,116,112,115,58,47,
47,112,99,101,109,45,101,109,117,108,97,116,111,114,46,99,111,46,117,107,
47,92,110,92,110,84,104,105,115,32,112,114,111,103,114,97,109,32,105,115,
32,108,105,99,101,110,115,101,100,32,117,110,100,101,114,32,116,104,101,
diff --git a/src/wx-sdl2-display-win.c b/src/wx-sdl2-display-win.c
index f1062d5..461ba16 100644
--- a/src/wx-sdl2-display-win.c
+++ b/src/wx-sdl2-display-win.c
@@ -68,6 +68,15 @@ extern void device_force_redraw();
extern void mouse_wheel_update(int);
extern void toggle_fullscreen();
+/*Minimum window width to prevent menu wrapping.
+ This is a horrible hack to work around issues with PCem, SDL2, and the
+ AdjustWindowRectEx() function. Allowing the menu to wrap causes some quite odd
+ window behaviour, mainly shooting to the bottom of the screen when you try to
+ move it.
+ This hard coded limit is highly fragile and will be replaced by a proper fix as
+ soon as I work out what that should be!*/
+#define MIN_WIDTH 360
+
void display_resize(int width, int height)
{
winsizex = width*(video_scale+1) >> 1;
@@ -81,6 +90,8 @@ void display_resize(int width, int height)
winsizex = rect.w;
winsizey = rect.h;
+ if (winsizex < MIN_WIDTH)
+ winsizex = MIN_WIDTH;
win_doresize = 1;
}
@@ -584,7 +595,7 @@ int window_create()
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
- "PCem v14", /* Title Text */
+ "PCem " PCEM_VERSION_STRING, /* Title Text */
WS_OVERLAPPEDWINDOW&~WS_SIZEBOX, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
@@ -769,7 +780,7 @@ int render()
break;
}
}
- if (rawinputkey[sdl_scancode(SDL_SCANCODE_PAGEDOWN)] &&
+ if ((rawinputkey[sdl_scancode(SDL_SCANCODE_PAGEDOWN)] || rawinputkey[sdl_scancode(SDL_SCANCODE_KP_3)]) &&
(rawinputkey[sdl_scancode(SDL_SCANCODE_LCTRL)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RCTRL)]) &&
(rawinputkey[sdl_scancode(SDL_SCANCODE_LALT)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RALT)]))
trigger_fullscreen = 1;
@@ -778,7 +789,7 @@ int render()
trigger_fullscreen = 0;
toggle_fullscreen();
}
- else if (rawinputkey[sdl_scancode(SDL_SCANCODE_PAGEUP)] &&
+ else if ((rawinputkey[sdl_scancode(SDL_SCANCODE_PAGEUP)] || rawinputkey[sdl_scancode(SDL_SCANCODE_KP_9)]) &&
(rawinputkey[sdl_scancode(SDL_SCANCODE_LCTRL)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RCTRL)]) &&
(rawinputkey[sdl_scancode(SDL_SCANCODE_LALT)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RALT)]))
trigger_screenshot = 1;
@@ -787,7 +798,7 @@ int render()
trigger_screenshot = 0;
take_screenshot = 1;
}
- else if (event.key.keysym.scancode == SDL_SCANCODE_END &&
+ else if ((event.key.keysym.scancode == SDL_SCANCODE_END || event.key.keysym.scancode == SDL_SCANCODE_KP_1) &&
(rawinputkey[sdl_scancode(SDL_SCANCODE_LCTRL)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RCTRL)]))
trigger_inputrelease = 1;
else if (trigger_inputrelease)
diff --git a/src/wx-sdl2-display.c b/src/wx-sdl2-display.c
index 0de48c5..ac8c23e 100644
--- a/src/wx-sdl2-display.c
+++ b/src/wx-sdl2-display.c
@@ -541,7 +541,7 @@ int render()
}
}
}
- if (rawinputkey[sdl_scancode(SDL_SCANCODE_PAGEDOWN)] &&
+ if ((rawinputkey[sdl_scancode(SDL_SCANCODE_PAGEDOWN)] || rawinputkey[sdl_scancode(SDL_SCANCODE_KP_3)]) &&
(rawinputkey[sdl_scancode(SDL_SCANCODE_LCTRL)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RCTRL)]) &&
(rawinputkey[sdl_scancode(SDL_SCANCODE_LALT)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RALT)]))
trigger_fullscreen = 1;
@@ -550,7 +550,7 @@ int render()
trigger_fullscreen = 0;
toggle_fullscreen();
}
- else if (rawinputkey[sdl_scancode(SDL_SCANCODE_PAGEUP)] &&
+ else if ((rawinputkey[sdl_scancode(SDL_SCANCODE_PAGEUP)] || rawinputkey[sdl_scancode(SDL_SCANCODE_KP_9)]) &&
(rawinputkey[sdl_scancode(SDL_SCANCODE_LCTRL)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RCTRL)]) &&
(rawinputkey[sdl_scancode(SDL_SCANCODE_LALT)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RALT)]))
trigger_screenshot = 1;
@@ -559,7 +559,7 @@ int render()
trigger_screenshot = 0;
take_screenshot = 1;
}
- else if (event.key.keysym.scancode == SDL_SCANCODE_END &&
+ else if ((event.key.keysym.scancode == SDL_SCANCODE_END || event.key.keysym.scancode == SDL_SCANCODE_KP_1) &&
(rawinputkey[sdl_scancode(SDL_SCANCODE_LCTRL)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RCTRL)]))
trigger_inputrelease = 1;
else if (trigger_inputrelease)
diff --git a/src/wx-sdl2-keyboard.c b/src/wx-sdl2-keyboard.c
index 12eb626..adf8e8a 100644
--- a/src/wx-sdl2-keyboard.c
+++ b/src/wx-sdl2-keyboard.c
@@ -1,7 +1,7 @@
#include "plat-keyboard.h"
#include
-int pcem_key[272];
+uint8_t pcem_key[272];
int rawinputkey[272];
void keyboard_init()
diff --git a/src/wx-sdl2-video-gl3.c b/src/wx-sdl2-video-gl3.c
index f8895b3..3e4330c 100644
--- a/src/wx-sdl2-video-gl3.c
+++ b/src/wx-sdl2-video-gl3.c
@@ -559,7 +559,7 @@ static glsl_t* load_glslp(glsl_t* glsl, int num_shader, const char* f)
if (p)
{
char path[512];
- char file[512];
+ char file[1024];
int failed = 0;
strcpy(path, f);
char* filename = get_filename(path);
@@ -769,6 +769,12 @@ int gl3_init(SDL_Window* window, sdl_render_driver requested_render_driver, SDL_
strcpy(current_render_driver_name, requested_render_driver.name);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+#ifdef __APPLE__
+ // without an explicit request for the core profile 3.0 macOS falls back to default ancient 2.1
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+#endif
context = SDL_GL_CreateContext(window);
@@ -1637,12 +1643,21 @@ int gl3_renderer_available(struct sdl_render_driver* driver)
if (available < 0)
{
available = 0;
+
+ // GL SetAttribute should be done *before* window creation for the attributes to apply on
+ // context creation (seems to depend on OpenGL impl. but it souldn't hurt other platforms
+ // to do it here (earlier than before)
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+
+#ifdef __APPLE__
+ // without an explicit request for the core profile 3.0 macOS falls back to default ancient 2.1
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+#endif
+
SDL_Window* window = SDL_CreateWindow("GL3 test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1, 1, SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL);
if (window)
{
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
-
SDL_GLContext context = SDL_GL_CreateContext(window);
if (context)
{
diff --git a/src/wx-sdl2.c b/src/wx-sdl2.c
index 50e7a44..984d731 100644
--- a/src/wx-sdl2.c
+++ b/src/wx-sdl2.c
@@ -18,6 +18,8 @@
#include
#include
#include "ibm.h"
+#include "device.h"
+#include "cassette.h"
#include "cdrom-ioctl.h"
#include "cdrom-image.h"
#include "config.h"
@@ -48,6 +50,8 @@
#include
#include
#undef pause
+#include
+#include
#endif
extern void creatediscimage_open(void *hwnd);
@@ -221,6 +225,14 @@ int mainthread(void* param)
return TRUE;
}
+void stop_emulation_now(void)
+{
+ /*Deduct a sufficiently large number of cycles that no instructions will
+ run before the main thread is terminated*/
+ cycles -= 99999999;
+ wx_stop_emulation_now(ghwnd);
+}
+
int dir_exists(char* path)
{
return wx_dir_exists(path);
@@ -231,12 +243,32 @@ void get_pcem_path(char *s, int size)
#ifdef __linux
wx_get_home_directory(s);
strcat(s, ".pcem/");
+#elif defined(__APPLE__)
+ /*TODO: Use CoreFoundation functions to get proper directory, in case
+ the Application Support directory is different (I.E., with signing)*/
+ wx_get_home_directory(s);
+ strcat(s, "Library/Application Support/PCem/");
+
+ struct stat st = {0};
+
+ // create ~/Library/Application Support/PCem/
+ // if it doesn't exist
+ if (stat(s, &st) == -1)
+ {
+ mkdir(s, 0700);
+ }
#else
char* path = SDL_GetBasePath();
strcpy(s, path);
#endif
}
+void get_pcem_base_path(char *s, int size)
+{
+ char* path = SDL_GetBasePath();
+ strcpy(s, path);
+}
+
void set_window_title(const char *s)
{
sdl_set_window_title(s);
@@ -502,7 +534,7 @@ int pc_main(int argc, char** argv)
paths_init();
#ifdef __linux__
- char s[512];
+ char s[1024];
/* create directories if they don't exist */
if (!wx_setup(pcem_path))
return FALSE;
@@ -711,6 +743,7 @@ int stop_emulation()
endblit();
SDL_DestroyMutex(ghMutex);
+ device_close_all();
midi_close();
pclog("Emulation stopped.\n");
@@ -759,6 +792,16 @@ int getsfile(void* hwnd, char *f, char *fn, char *dir, char *ext)
return ret;
}
+int getfilewithcaption(void* hwnd, char *f, char *fn, char *caption)
+{
+ int ret = wx_filedialog(hwnd, caption, fn, f, 0, 1, openfilestring);
+#ifdef __APPLE__
+ /* wxWidgets on OSX may mess up the SDL-window somehow, so just in case we reset it here */
+ window_doreset = 1;
+#endif
+ return ret;
+}
+
void atapi_close(void)
{
switch (cdrom_drive)
@@ -899,6 +942,22 @@ int wx_handle_command(void* hwnd, int wParam, int checked)
{
zip_eject();
}
+ else if (ID_IS("IDM_CASSETTE_LOAD"))
+ {
+ if (!getfile(hwnd,
+ "Tape image (*.pzxi;*.pzx)|*.pzxi;*.pzx|All files (*.*)|*.*",
+ cassettefn))
+ {
+ cassette_eject();
+ cassette_load(openfilestring);
+ saveconfig(NULL);
+ }
+ }
+ else if (ID_IS("IDM_CASSETTE_EJECT"))
+ {
+ cassette_eject();
+ saveconfig(NULL);
+ }
else if (ID_IS("IDM_MACHINE_TOGGLE"))
{
if (emulation_state != EMULATION_STOPPED)
diff --git a/src/wx-sdl2.h b/src/wx-sdl2.h
index fdc45ef..233ceab 100644
--- a/src/wx-sdl2.h
+++ b/src/wx-sdl2.h
@@ -5,6 +5,7 @@ extern "C" {
void leave_fullscreen();
int getfile(void* hwnd, char *f, char *fn);
int getsfile(void* hwnd, char *f, char *fn, char *dir, char *ext);
+int getfilewithcaption(void* hwnd, char *f, char *fn, char *caption);
void screenshot_taken(unsigned char* rgb, int width, int height);
#ifdef __cplusplus
diff --git a/src/wx-thread.c b/src/wx-thread.c
index 1ab591f..c3797f6 100644
--- a/src/wx-thread.c
+++ b/src/wx-thread.c
@@ -1,6 +1,9 @@
#include
#include
#include
+#ifdef __APPLE__
+#include
+#endif
#include "thread.h"
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include
@@ -69,6 +72,43 @@ void thread_destroy_event(event_t *_event)
free(event);
}
+typedef struct win_mutex_t
+{
+ HANDLE handle;
+} win_mutex_t;
+
+mutex_t *thread_create_mutex(void)
+{
+ win_mutex_t *mutex = malloc(sizeof(win_mutex_t));
+
+ mutex->handle = CreateSemaphore(NULL, 1, 1, NULL);
+
+ return mutex;
+
+}
+
+void thread_lock_mutex(mutex_t *_mutex)
+{
+ win_mutex_t *mutex = (win_mutex_t *)_mutex;
+
+ WaitForSingleObject(mutex->handle, INFINITE);
+}
+
+void thread_unlock_mutex(mutex_t *_mutex)
+{
+ win_mutex_t *mutex = (win_mutex_t *)_mutex;
+
+ ReleaseSemaphore(mutex->handle, 1, NULL);
+}
+
+void thread_destroy_mutex(mutex_t *_mutex)
+{
+ win_mutex_t *mutex = (win_mutex_t *)_mutex;
+
+ CloseHandle(mutex->handle);
+
+ free(mutex);
+}
#else
#include
#include
@@ -177,4 +217,43 @@ void thread_sleep(int t)
{
usleep(t * 1000);
}
+
+
+typedef struct pt_mutex_t
+{
+ pthread_mutex_t mutex;
+} pt_mutex_t;
+
+mutex_t *thread_create_mutex(void)
+{
+ pt_mutex_t *mutex = malloc(sizeof(pt_mutex_t));
+
+ pthread_mutex_init(&mutex->mutex, NULL);
+
+ return mutex;
+
+}
+
+void thread_lock_mutex(mutex_t *_mutex)
+{
+ pt_mutex_t *mutex = (pt_mutex_t *)_mutex;
+
+ pthread_mutex_lock(&mutex->mutex);
+}
+
+void thread_unlock_mutex(mutex_t *_mutex)
+{
+ pt_mutex_t *mutex = (pt_mutex_t *)_mutex;
+
+ pthread_mutex_unlock(&mutex->mutex);
+}
+
+void thread_destroy_mutex(mutex_t *_mutex)
+{
+ pt_mutex_t *mutex = (pt_mutex_t *)_mutex;
+
+ pthread_mutex_destroy(&mutex->mutex);
+
+ free(mutex);
+}
#endif
diff --git a/src/wx-utils.cc b/src/wx-utils.cc
index 561eeea..2facbea 100644
--- a/src/wx-utils.cc
+++ b/src/wx-utils.cc
@@ -115,8 +115,10 @@ void wx_checkmenuitem(void* menu, int id, int checked)
if (item)
item->Check(checked);
+#ifndef RELEASE_BUILD
else
std::cout << "Menu item not found: " << id << std::endl;
+#endif
}
void wx_enablemenuitem(void* menu, int id, int enable)
@@ -129,8 +131,10 @@ void wx_enablemenuitem(void* menu, int id, int enable)
if (item)
item->Enable(enable);
+#ifndef RELEASE_BUILD
else
std::cout << "Menu item not found: " << id << std::endl;
+#endif
}
void* wx_getsubmenu(void* menu, int id)
@@ -402,6 +406,21 @@ int wx_sendmessage(void* window, int type, LONG_PARAM param1, LONG_PARAM param2)
((wxWindow *)window)->Reparent((wxWindow *)param1);
break;
}
+ case WX_WM_ENABLE:
+ {
+ ((wxWindow*)window)->Enable((bool)param2);
+ break;
+ }
+ case WX_WM_SHOW:
+ {
+ ((wxWindow*)window)->Show((bool)param2);
+ break;
+ }
+ case WX_WM_LAYOUT:
+ {
+ ((wxWindow*)window)->Layout();
+ break;
+ }
}
((wxWindow*)window)->Fit();
@@ -434,6 +453,13 @@ void wx_stop_emulation(void* window)
wxQueueEvent((wxWindow*)window, event);
}
+void wx_stop_emulation_now(void* window)
+{
+ wxCommandEvent* event = new wxCommandEvent(WX_STOP_EMULATION_NOW_EVENT, wxID_ANY);
+ event->SetEventObject((wxWindow*)window);
+ wxQueueEvent((wxWindow*)window, event);
+}
+
int wx_yield()
{
return wxYield();
diff --git a/src/wx-utils.h b/src/wx-utils.h
index 945d54f..0b12970 100644
--- a/src/wx-utils.h
+++ b/src/wx-utils.h
@@ -52,6 +52,7 @@ extern "C" {
void wx_exit(void* window, int value);
void wx_stop_emulation(void* window);
+ void wx_stop_emulation_now(void* window);
void* wx_createtimer(void (*fn)());
void wx_starttimer(void* timer, int milliseconds, int once);
@@ -152,9 +153,14 @@ extern void (*wx_idle_func)(void* window, void* event);
#define WX_REPARENT 72
+#define WX_WM_ENABLE 80
+#define WX_WM_SHOW 81
+#define WX_WM_LAYOUT 82
+#define WX_MB_YES wxYES
#define WX_MB_OK wxOK
#define WX_MB_OKCANCEL wxOK|wxCANCEL
+#define WX_MB_NODEFAULT wxYES_NO|wxNO_DEFAULT
#define WX_IDOK wxOK
#define IMAGE_JPG "jpg"
diff --git a/src/x86.h b/src/x86.h
index a9365c0..f0f2238 100644
--- a/src/x86.h
+++ b/src/x86.h
@@ -39,8 +39,8 @@ typedef union
typedef struct
{
uint32_t base;
- uint32_t limit;
- uint8_t access;
+ uint32_t limit, limit_raw;
+ uint8_t access, access2;
uint16_t seg;
uint32_t limit_low, limit_high;
int checked; /*Non-zero if selector is known to be valid*/
@@ -90,6 +90,7 @@ struct
int8_t ssegs;
int8_t ismmx;
int8_t abrt;
+ int8_t smi_pending;
int _cycles;
int cpu_recomp_ins;
@@ -118,11 +119,14 @@ struct
} CR0;
uint16_t flags, eflags;
+
+ uint32_t smbase;
} cpu_state;
#define cpu_state_offset(MEMBER) ((uintptr_t)&cpu_state.MEMBER - (uintptr_t)&cpu_state - 128)
#define cycles cpu_state._cycles
+extern int cycles_main;
#define cr0 cpu_state.CR0.l
#define msw cpu_state.CR0.w
@@ -175,6 +179,9 @@ extern x86seg gdt, ldt, idt, tr;
extern uint32_t cr2, cr3, cr4;
extern uint32_t dr[8];
+extern uint16_t sysenter_cs;
+extern uint32_t sysenter_eip, sysenter_esp;
+
extern uint16_t cpu_cur_status;
@@ -184,6 +191,7 @@ extern uint16_t cpu_cur_status;
#define CPU_STATUS_STACK32 (1 << 1)
#define CPU_STATUS_PMODE (1 << 2)
#define CPU_STATUS_V86 (1 << 3)
+#define CPU_STATUS_SMM (1 << 4)
#define CPU_STATUS_FLAGS 0xff
/*If the flags below are set in cpu_cur_status, they must be set in block->status.
@@ -258,6 +266,16 @@ enum
ABRT_PF = 0xE
};
+#define ABRT_MASK 0x7f
+/*An 'expected' exception is one that would be expected to occur on every execution
+ of this code path; eg a GPF due to being in v86 mode. An 'unexpected' exception is
+ one that would be unlikely to occur on the next exception, eg a page fault may be
+ fixed up by the exception handler and the next execution would not hit it.
+
+ This distinction is used by the dynarec; a block that hits an 'expected' exception
+ would be compiled, a block that hits an 'unexpected' exception would be rejected so
+ that we don't end up with an unnecessarily short block*/
+#define ABRT_EXPECTED 0x80
extern uint32_t abrt_error;
void x86_doabrt(int x86_abrt);
@@ -272,6 +290,7 @@ void x86illegal();
void x86seg_reset();
void x86gpf(char *s, uint16_t error);
+void x86gpf_expected(char *s, uint16_t error);
void resetx86();
void softresetx86();
@@ -294,7 +313,32 @@ void x86_int(int num);
void x86_int_sw(int num);
int x86_int_sw_rm(int num);
+void sysenter(void);
+void sysexit(void);
+
int divl(uint32_t val);
int idivl(int32_t val);
+extern int cpu_end_block_after_ins;
+
+void x86_smi_trigger(void);
+void x86_smi_enter(void);
+void x86_smi_leave(void);
+
+void cyrix_load_seg_descriptor(uint32_t addr, x86seg *seg);
+void cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg);
+
+#define SMHR_VALID (1 << 0)
+#define SMHR_ADDR_MASK (0xfffffffc)
+
+struct
+{
+ struct
+ {
+ uint32_t base;
+ uint64_t size;
+ } arr[8];
+ uint32_t smhr;
+} cyrix;
+
#endif
diff --git a/src/x86_ops.h b/src/x86_ops.h
index 73a0b6f..578b7cf 100644
--- a/src/x86_ops.h
+++ b/src/x86_ops.h
@@ -38,6 +38,10 @@ extern OpFn dynarec_ops_winchip2_0f[1024];
extern OpFn dynarec_ops_pentium_0f[1024];
extern OpFn dynarec_ops_pentiummmx_0f[1024];
+extern OpFn dynarec_ops_pentiumpro_0f[1024];
+extern OpFn dynarec_ops_pentium2_0f[1024];
+
+extern OpFn dynarec_ops_c6x86_0f[1024];
extern OpFn dynarec_ops_c6x86mx_0f[1024];
extern OpFn dynarec_ops_fpu_d8_a16[32];
@@ -104,7 +108,10 @@ extern OpFn ops_winchip2_0f[1024];
extern OpFn ops_pentium_0f[1024];
extern OpFn ops_pentiummmx_0f[1024];
+extern OpFn ops_pentiumpro_0f[1024];
+extern OpFn ops_pentium2_0f[1024];
+extern OpFn ops_c6x86_0f[1024];
extern OpFn ops_c6x86mx_0f[1024];
extern OpFn ops_fpu_d8_a16[32];
diff --git a/src/x86_ops_3dnow.h b/src/x86_ops_3dnow.h
index 9f852d5..3ac36cb 100644
--- a/src/x86_ops_3dnow.h
+++ b/src/x86_ops_3dnow.h
@@ -20,7 +20,7 @@ static int opPREFETCH_a32(uint32_t fetchdat)
static int opFEMMS(uint32_t fetchdat)
{
ILLEGAL_ON(!cpu_has_feature(CPU_FEATURE_MMX));
- if (cr0 & 4)
+ if (cr0 & 0xc)
{
x86_int(7);
return 1;
diff --git a/src/x86_ops_cyrix.h b/src/x86_ops_cyrix.h
new file mode 100644
index 0000000..e6464ce
--- /dev/null
+++ b/src/x86_ops_cyrix.h
@@ -0,0 +1,274 @@
+/*Cyrix-only instructions*/
+/*System Management Mode*/
+static void opSVDC_common(uint32_t fetchdat)
+{
+ switch (rmdat & 0x38)
+ {
+ case 0x00: /*ES*/
+ cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_es);
+ writememw(0, easeg+cpu_state.eaaddr+8, ES);
+ break;
+ case 0x08: /*CS*/
+ cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_cs);
+ writememw(0, easeg+cpu_state.eaaddr+8, CS);
+ break;
+ case 0x18: /*DS*/
+ cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_ds);
+ writememw(0, easeg+cpu_state.eaaddr+8, DS);
+ break;
+ case 0x10: /*SS*/
+ cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_ss);
+ writememw(0, easeg+cpu_state.eaaddr+8, SS);
+ break;
+ case 0x20: /*FS*/
+ cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_fs);
+ writememw(0, easeg+cpu_state.eaaddr+8, FS);
+ break;
+ case 0x28: /*GS*/
+ cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_gs);
+ writememw(0, easeg+cpu_state.eaaddr+8, GS);
+ break;
+ default:
+ pclog("opSVDC: unknown rmdat %02x\n", rmdat);
+ x86illegal();
+ }
+}
+static int opSVDC_a16(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ {
+ fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+ opSVDC_common(fetchdat);
+ }
+ else
+ x86illegal();
+
+ return cpu_state.abrt;
+}
+static int opSVDC_a32(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ {
+ fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+ opSVDC_common(fetchdat);
+ }
+ else
+ x86illegal();
+
+ return cpu_state.abrt;
+}
+
+static void opRSDC_common(uint32_t fetchdat)
+{
+ switch (rmdat & 0x38)
+ {
+ case 0x00: /*ES*/
+ cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_es);
+ break;
+ case 0x18: /*DS*/
+ cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_ds);
+ break;
+ case 0x10: /*SS*/
+ cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_ss);
+ break;
+ case 0x20: /*FS*/
+ cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_fs);
+ break;
+ case 0x28: /*GS*/
+ cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_gs);
+ break;
+ default:
+ pclog("opRSDC: unknown rmdat %02x\n", rmdat);
+ x86illegal();
+ }
+}
+static int opRSDC_a16(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ {
+ fetch_ea_16(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ opRSDC_common(fetchdat);
+ }
+ else
+ x86illegal();
+
+ return cpu_state.abrt;
+}
+static int opRSDC_a32(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ {
+ fetch_ea_32(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ opRSDC_common(fetchdat);
+ }
+ else
+ x86illegal();
+
+ return cpu_state.abrt;
+}
+
+static int opSVLDT_a16(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ {
+ fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+ cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &ldt);
+ writememw(0, easeg+cpu_state.eaaddr+8, ldt.seg);
+ }
+ else
+ x86illegal();
+
+ return cpu_state.abrt;
+}
+static int opSVLDT_a32(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ {
+ fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+ cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &ldt);
+ writememw(0, easeg+cpu_state.eaaddr+8, ldt.seg);
+ }
+ else
+ x86illegal();
+
+ return cpu_state.abrt;
+}
+
+static int opRSLDT_a16(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ {
+ fetch_ea_16(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &ldt);
+ }
+ else
+ x86illegal();
+
+ return cpu_state.abrt;
+}
+static int opRSLDT_a32(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ {
+ fetch_ea_32(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &ldt);
+ }
+ else
+ x86illegal();
+
+ return cpu_state.abrt;
+}
+
+static int opSVTS_a16(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ {
+ fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+ cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &tr);
+ writememw(0, easeg+cpu_state.eaaddr+8, tr.seg);
+ }
+ else
+ x86illegal();
+
+ return cpu_state.abrt;
+}
+static int opSVTS_a32(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ {
+ fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+ cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &tr);
+ writememw(0, easeg+cpu_state.eaaddr+8, tr.seg);
+ }
+ else
+ x86illegal();
+
+ return cpu_state.abrt;
+}
+
+static int opRSTS_a16(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ {
+ fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+ cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &tr);
+ writememw(0, easeg+cpu_state.eaaddr+8, tr.seg);
+ }
+ else
+ x86illegal();
+
+ return cpu_state.abrt;
+}
+static int opRSTS_a32(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ {
+ fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+ cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &tr);
+ writememw(0, easeg+cpu_state.eaaddr+8, tr.seg);
+ }
+ else
+ x86illegal();
+
+ return cpu_state.abrt;
+}
+
+static int opSMINT(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ fatal("opSMINT\n");
+ else
+ x86illegal();
+
+ return 1;
+}
+
+static int opRDSHR_a16(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ fatal("opRDSHR_a16\n");
+ else
+ x86illegal();
+
+ return 1;
+}
+static int opRDSHR_a32(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ fatal("opRDSHR_a32\n");
+ else
+ x86illegal();
+
+ return 1;
+}
+
+static int opWRSHR_a16(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ fatal("opWRSHR_a16\n");
+ else
+ x86illegal();
+
+ return 1;
+}
+static int opWRSHR_a32(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ fatal("opWRSHR_a32\n");
+ else
+ x86illegal();
+
+ return 1;
+}
diff --git a/src/x86_ops_flag.h b/src/x86_ops_flag.h
index db1dc20..64f43e9 100644
--- a/src/x86_ops_flag.h
+++ b/src/x86_ops_flag.h
@@ -85,8 +85,10 @@ static int opSTI(uint32_t fetchdat)
else
cpu_state.flags |= I_FLAG;
- CPU_BLOCK_END();
-
+ /*First instruction after STI will always execute, regardless of whether
+ there is a pending interrupt*/
+ cpu_end_block_after_ins = 2;
+
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0);
return 0;
diff --git a/src/x86_ops_int.h b/src/x86_ops_int.h
index efb2a5d..3ac96f3 100644
--- a/src/x86_ops_int.h
+++ b/src/x86_ops_int.h
@@ -59,7 +59,7 @@ static int opINT(uint32_t fetchdat)
}
}
}
- x86gpf(NULL,0);
+ x86gpf_expected(NULL,0);
return 1;
}
// /*if (temp == 0x10 && AH == 0xe) */pclog("INT %02X : %04X %04X %04X %04X %c %04X:%04X\n", temp, AX, BX, CX, DX, (AL < 32) ? ' ' : AL, CS, pc);
diff --git a/src/x86_ops_io.h b/src/x86_ops_io.h
index d427a7f..cd18934 100644
--- a/src/x86_ops_io.h
+++ b/src/x86_ops_io.h
@@ -5,6 +5,8 @@ static int opIN_AL_imm(uint32_t fetchdat)
AL = inb(port);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0);
+ if (cpu_state.smi_pending)
+ return 1;
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
@@ -17,6 +19,8 @@ static int opIN_AX_imm(uint32_t fetchdat)
AX = inw(port);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0);
+ if (cpu_state.smi_pending)
+ return 1;
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
@@ -31,6 +35,8 @@ static int opIN_EAX_imm(uint32_t fetchdat)
EAX = inl(port);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 2, -1, 0,1,0,0, 0);
+ if (cpu_state.smi_pending)
+ return 1;
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
@@ -43,10 +49,12 @@ static int opOUT_AL_imm(uint32_t fetchdat)
outb(port, AL);
CLOCK_CYCLES(10);
PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0);
- if (port == 0x64)
- return x86_was_reset;
+ if (cpu_state.smi_pending)
+ return 1;
if (nmi && nmi_enable && nmi_mask)
return 1;
+ if (port == 0x64)
+ return x86_was_reset;
return 0;
}
static int opOUT_AX_imm(uint32_t fetchdat)
@@ -57,6 +65,8 @@ static int opOUT_AX_imm(uint32_t fetchdat)
outw(port, AX);
CLOCK_CYCLES(10);
PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0);
+ if (cpu_state.smi_pending)
+ return 1;
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
@@ -71,6 +81,8 @@ static int opOUT_EAX_imm(uint32_t fetchdat)
outl(port, EAX);
CLOCK_CYCLES(10);
PREFETCH_RUN(10, 2, -1, 0,0,0,1, 0);
+ if (cpu_state.smi_pending)
+ return 1;
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
@@ -82,6 +94,8 @@ static int opIN_AL_DX(uint32_t fetchdat)
AL = inb(DX);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0);
+ if (cpu_state.smi_pending)
+ return 1;
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
@@ -93,6 +107,8 @@ static int opIN_AX_DX(uint32_t fetchdat)
AX = inw(DX);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0);
+ if (cpu_state.smi_pending)
+ return 1;
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
@@ -106,6 +122,8 @@ static int opIN_EAX_DX(uint32_t fetchdat)
EAX = inl(DX);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 1, -1, 0,1,0,0, 0);
+ if (cpu_state.smi_pending)
+ return 1;
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
@@ -117,6 +135,8 @@ static int opOUT_AL_DX(uint32_t fetchdat)
outb(DX, AL);
CLOCK_CYCLES(11);
PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0);
+ if (cpu_state.smi_pending)
+ return 1;
if (nmi && nmi_enable && nmi_mask)
return 1;
return x86_was_reset;
@@ -129,6 +149,8 @@ static int opOUT_AX_DX(uint32_t fetchdat)
outw(DX, AX);
CLOCK_CYCLES(11);
PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0);
+ if (cpu_state.smi_pending)
+ return 1;
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
@@ -141,6 +163,8 @@ static int opOUT_EAX_DX(uint32_t fetchdat)
check_io_perm(DX + 3);
outl(DX, EAX);
PREFETCH_RUN(11, 1, -1, 0,0,0,1, 0);
+ if (cpu_state.smi_pending)
+ return 1;
if (nmi && nmi_enable && nmi_mask)
return 1;
return 0;
diff --git a/src/x86_ops_misc.h b/src/x86_ops_misc.h
index aa81a2c..4dc7566 100644
--- a/src/x86_ops_misc.h
+++ b/src/x86_ops_misc.h
@@ -970,3 +970,39 @@ static int opWRMSR(uint32_t fetchdat)
return 1;
}
+static int opSYSENTER(uint32_t fetchdat)
+{
+ if (!(cr0 & 1) || !(sysenter_cs & 0xfffc))
+ {
+ x86gpf(NULL,0);
+ return 1;
+ }
+// pclog("opSYSENTER: CS=%04x EIP=%08x ESP=%08x %04x:%08x %i\n", sysenter_cs, sysenter_eip, sysenter_esp, CS,cpu_state.pc, times);
+ sysenter();
+ CPU_BLOCK_END();
+ return 0;
+}
+
+static int opSYSEXIT(uint32_t fetchdat)
+{
+ if (!(cr0 & 1) || !(sysenter_cs & 0xfffc) || CPL)
+ {
+ x86gpf(NULL,0);
+ return 1;
+ }
+// pclog("opSYSEXIT\n");
+ sysexit();
+ CPU_BLOCK_END();
+ return 0;
+}
+
+static int opHINTNOP_a16(uint32_t fetchdat)
+{
+ fetch_ea_16(fetchdat);
+ return 0;
+}
+static int opHINTNOP_a32(uint32_t fetchdat)
+{
+ fetch_ea_32(fetchdat);
+ return 0;
+}
diff --git a/src/x86_ops_mmx.h b/src/x86_ops_mmx.h
index 95ed658..712d185 100644
--- a/src/x86_ops_mmx.h
+++ b/src/x86_ops_mmx.h
@@ -38,7 +38,7 @@ static int opEMMS(uint32_t fetchdat)
x86illegal();
return 1;
}
- if (cr0 & 4)
+ if (cr0 & 0xc)
{
x86_int(7);
return 1;
diff --git a/src/x86_ops_mmx_mov.h b/src/x86_ops_mmx_mov.h
index 133d48d..548b6c4 100644
--- a/src/x86_ops_mmx_mov.h
+++ b/src/x86_ops_mmx_mov.h
@@ -50,7 +50,7 @@ static int opMOVD_l_mm_a32(uint32_t fetchdat)
static int opMOVD_mm_l_a16(uint32_t fetchdat)
{
MMX_ENTER();
-
+
fetch_ea_16(fetchdat);
if (cpu_mod == 3)
{
@@ -69,6 +69,52 @@ static int opMOVD_mm_l_a16(uint32_t fetchdat)
static int opMOVD_mm_l_a32(uint32_t fetchdat)
{
MMX_ENTER();
+
+ fetch_ea_32(fetchdat);
+ if (cpu_mod == 3)
+ {
+ cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].l[0];
+ CLOCK_CYCLES(1);
+ }
+ else
+ {
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+ CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3);
+ writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); if (cpu_state.abrt) return 1;
+ CLOCK_CYCLES(2);
+ }
+ return 0;
+}
+
+/*Cyrix maps both MOVD and SMINT to the same opcode*/
+static int opMOVD_mm_l_a16_cx(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ return opSMINT(fetchdat);
+
+ MMX_ENTER();
+
+ fetch_ea_16(fetchdat);
+ if (cpu_mod == 3)
+ {
+ cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].l[0];
+ CLOCK_CYCLES(1);
+ }
+ else
+ {
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+ CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3);
+ writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); if (cpu_state.abrt) return 1;
+ CLOCK_CYCLES(2);
+ }
+ return 0;
+}
+static int opMOVD_mm_l_a32_cx(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ return opSMINT(fetchdat);
+
+ MMX_ENTER();
fetch_ea_32(fetchdat);
if (cpu_mod == 3)
diff --git a/src/x86_ops_pmode.h b/src/x86_ops_pmode.h
index 5301ef3..3578b5f 100644
--- a/src/x86_ops_pmode.h
+++ b/src/x86_ops_pmode.h
@@ -165,7 +165,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32)
int dpl, valid, granularity;
uint32_t addr, base, limit;
uint16_t desc, sel;
- uint8_t access;
+ uint8_t access, access2;
// pclog("op0F00 %02X %04X:%04X\n", rmdat & 0x38, CS, pc);
switch (rmdat & 0x38)
@@ -198,10 +198,13 @@ static int op0F00_common(uint32_t fetchdat, int ea32)
limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16);
base = (readmemw(0, addr + 2)) | (readmemb(0, addr + 4) << 16) | (readmemb(0, addr + 7) << 24);
access = readmemb(0, addr + 5);
+ access2 = readmemb(0, addr + 6);
granularity = readmemb(0, addr + 6) & 0x80;
if (cpu_state.abrt) return 1;
ldt.limit = limit;
+ ldt.limit_raw = limit;
ldt.access = access;
+ ldt.access2 = access2;
if (granularity)
{
ldt.limit <<= 12;
@@ -226,6 +229,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32)
limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16);
base = (readmemw(0, addr + 2)) | (readmemb(0, addr + 4) << 16) | (readmemb(0, addr + 7) << 24);
access = readmemb(0, addr + 5);
+ access2 = readmemb(0, addr + 6);
granularity = readmemb(0, addr + 6) & 0x80;
if (cpu_state.abrt) return 1;
access |= 2;
@@ -233,7 +237,9 @@ static int op0F00_common(uint32_t fetchdat, int ea32)
if (cpu_state.abrt) return 1;
tr.seg = sel;
tr.limit = limit;
+ tr.limit_raw = limit;
tr.access = access;
+ tr.access2 = access2;
if (granularity)
{
tr.limit <<= 12;
@@ -470,3 +476,14 @@ static int op0F01_286(uint32_t fetchdat)
return op0F01_common(fetchdat, 0, 1, 0);
}
+
+
+static int opRSM(uint32_t fetchdat)
+{
+ if (cpu_cur_status & CPU_STATUS_SMM)
+ x86_smi_leave();
+ else
+ x86illegal();
+
+ return 1;
+}
diff --git a/src/x86_ops_ret.h b/src/x86_ops_ret.h
index 70ac327..3dd93f4 100644
--- a/src/x86_ops_ret.h
+++ b/src/x86_ops_ret.h
@@ -166,7 +166,7 @@ static int opIRET(uint32_t fetchdat)
}
else
{
- x86gpf(NULL,0);
+ x86gpf_expected(NULL,0);
return 1;
}
}
@@ -214,7 +214,7 @@ static int opIRETD(uint32_t fetchdat)
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
{
- x86gpf(NULL,0);
+ x86gpf_expected(NULL,0);
return 1;
}
if (msw & 1)
diff --git a/src/x86seg.c b/src/x86seg.c
index 21a3778..f2d465f 100644
--- a/src/x86seg.c
+++ b/src/x86seg.c
@@ -10,6 +10,7 @@
#include "cpu.h"
#include "config.h"
#include "paths.h"
+#include "i440bx.h"
/*Controls whether the accessed bit in a descriptor is set when CS is loaded.*/
#define CS_ACCESSED
@@ -61,6 +62,7 @@ void x86abort(const char *format, ...)
static void seg_reset(x86seg *s)
{
s->access = (0 << 5) | 2;
+ s->access2 = 0;
s->limit = 0xFFFF;
s->limit_low = 0;
s->limit_high = 0xffff;
@@ -161,10 +163,16 @@ void x86_doabrt(int x86_abrt)
}
void x86gpf(char *s, uint16_t error)
{
-// pclog("GPF %04X\n", error);
+// pclog("GPF %04X %04x(%08x):%08x\n", error, CS,cs,cpu_state.pc);
cpu_state.abrt = ABRT_GPF;
abrt_error = error;
}
+void x86gpf_expected(char *s, uint16_t error)
+{
+// pclog("GPF_v86 %04X %04x(%08x):%08x\n", error, CS,cs,cpu_state.pc);
+ cpu_state.abrt = ABRT_GPF | ABRT_EXPECTED;
+ abrt_error = error;
+}
void x86ss(char *s, uint16_t error)
{
// pclog("SS %04X\n", error);
@@ -211,12 +219,14 @@ static void set_use32(int u)
static void do_seg_load(x86seg *s, uint16_t *segdat)
{
s->limit = segdat[0] | ((segdat[3] & 0xF) << 16);
+ s->limit_raw = s->limit;
if (segdat[3] & 0x80)
s->limit = (s->limit << 12) | 0xFFF;
s->base = segdat[1] | ((segdat[2] & 0xFF) << 16);
if (is386)
s->base |= ((segdat[3] >> 8) << 24);
s->access = segdat[2] >> 8;
+ s->access2 = segdat[3] & 0xf0;
if ((segdat[2] & 0x1800) != 0x1000 || !(segdat[2] & (1 << 10))) /*expand-down*/
{
@@ -249,6 +259,7 @@ static void do_seg_load(x86seg *s, uint16_t *segdat)
static void do_seg_v86_init(x86seg *s)
{
s->access = (3 << 5) | 2;
+ s->access2 = 0;
s->limit = 0xffff;
s->limit_low = 0;
s->limit_high = 0xffff;
@@ -453,15 +464,16 @@ int loadseg(uint16_t seg, x86seg *s)
else
{
s->access = (3 << 5) | 2;
+ s->access2 = 0;
s->base = seg << 4;
s->seg = seg;
- if (s == &cpu_state.seg_ss)
- set_stack32(0);
s->checked = 1;
if (s == &cpu_state.seg_ds)
codegen_flat_ds = 0;
if (s == &cpu_state.seg_ss)
codegen_flat_ss = 0;
+ if (s == &cpu_state.seg_ss && (cpu_state.eflags & VM_FLAG))
+ set_stack32(0);
}
if (s == &cpu_state.seg_ds)
@@ -1124,6 +1136,7 @@ void loadcscall(uint16_t seg, uint32_t old_pc)
case 0x1800: case 0x1900: case 0x1A00: case 0x1B00: /*Non-conforming code*/
if (DPL < CPL)
{
+ uint16_t oldcs = CS;
oaddr = addr;
/*Load new stack*/
oldss=SS;
@@ -1239,6 +1252,7 @@ void loadcscall(uint16_t seg, uint32_t old_pc)
pclog("ABRT PUSHL\n");
SS = oldss;
ESP = oldsp2;
+ CS = oldcs;
return;
}
// if (output) pclog("Stack now %04X:%08X\n",SS,ESP);
@@ -1253,6 +1267,7 @@ void loadcscall(uint16_t seg, uint32_t old_pc)
pclog("ABRT COPYL\n");
SS = oldss;
ESP = oldsp2;
+ CS = oldcs;
return;
}
}
@@ -1270,6 +1285,7 @@ void loadcscall(uint16_t seg, uint32_t old_pc)
pclog("ABRT PUSHW\n");
SS = oldss;
ESP = oldsp2;
+ CS = oldcs;
return;
}
if (output) pclog("Write SP to %04X:%04X\n",SS,SP);
@@ -1288,6 +1304,7 @@ void loadcscall(uint16_t seg, uint32_t old_pc)
pclog("ABRT COPYW\n");
SS = oldss;
ESP = oldsp2;
+ CS = oldcs;
return;
}
}
@@ -1710,8 +1727,11 @@ void pmodeint(int num, int soft)
if (output) pclog("Addr %08X seg %04X %04X %04X %04X\n",addr,segdat[0],segdat[1],segdat[2],segdat[3]);
if (!(segdat[2]&0x1F00))
{
- //pclog("No seg\n");
- x86gpf(NULL,(num*8)+2);
+// pclog("No seg\n");
+ if (cpu_state.eflags & VM_FLAG) /*This fires on all V86 interrupts in EMM386. Mark as expected to prevent code churn*/
+ x86gpf_expected(NULL,(num*8)+2);
+ else
+ x86gpf(NULL,(num*8)+2);
return;
}
if (DPL>8;
}
+
+void sysenter(void)
+{
+ cpu_state.eflags &= ~VM_FLAG;
+ cpu_state.flags &= ~I_FLAG;
+
+ ESP = sysenter_esp;
+ cpu_state.pc = sysenter_eip;
+
+ cpu_state.seg_cs.seg = sysenter_cs & 0xfffc;
+ cpu_state.seg_cs.base = 0;
+ cpu_state.seg_cs.limit_low = 0;
+ cpu_state.seg_cs.limit = 0xffffffff;
+ cpu_state.seg_cs.limit_high = 0xffffffff;
+ cpu_state.seg_cs.access = 0x1b;
+ cpu_state.seg_cs.checked = 1;
+ oldcpl = 0;
+
+ cpu_state.seg_ss.seg = (sysenter_cs & 0xfffc) + 8;
+ cpu_state.seg_ss.base = 0;
+ cpu_state.seg_ss.limit_low = 0;
+ cpu_state.seg_ss.limit = 0xffffffff;
+ cpu_state.seg_ss.limit_high = 0xffffffff;
+ cpu_state.seg_ss.access = 0x13;
+ cpu_state.seg_ss.checked = 1;
+
+ cpu_cur_status &= ~(CPU_STATUS_NOTFLATSS | CPU_STATUS_V86);
+ cpu_cur_status |= (CPU_STATUS_USE32 | CPU_STATUS_STACK32 | CPU_STATUS_PMODE);
+ set_use32(1);
+ set_stack32(1);
+
+// pclog("syscall to %04x:%08x %04x:%08x\n", CS, cpu_state.pc, SS, ESP);
+}
+
+void sysexit(void)
+{
+ ESP = ECX;
+ cpu_state.pc = EDX;
+
+ cpu_state.seg_cs.seg = (sysenter_cs | 3) + 16;
+ cpu_state.seg_cs.base = 0;
+ cpu_state.seg_cs.limit_low = 0;
+ cpu_state.seg_cs.limit = 0xffffffff;
+ cpu_state.seg_cs.limit_high = 0xffffffff;
+ cpu_state.seg_cs.access = 0x7b;
+ cpu_state.seg_cs.checked = 1;
+ oldcpl = 3;
+
+ cpu_state.seg_ss.seg = (sysenter_cs | 3) + 24;
+ cpu_state.seg_ss.base = 0;
+ cpu_state.seg_ss.limit_low = 0;
+ cpu_state.seg_ss.limit = 0xffffffff;
+ cpu_state.seg_ss.limit_high = 0xffffffff;
+ cpu_state.seg_ss.access = 0x73;
+ cpu_state.seg_ss.checked = 1;
+
+ cpu_cur_status &= ~(CPU_STATUS_NOTFLATSS | CPU_STATUS_V86);
+ cpu_cur_status |= (CPU_STATUS_USE32 | CPU_STATUS_STACK32 | CPU_STATUS_PMODE);
+ flushmmucache_cr3();
+ set_use32(1);
+ set_stack32(1);
+
+// pclog("sysexit to %04x:%08x %04x:%08x\n", CS, cpu_state.pc, SS, ESP);
+}
+
+void x86_smi_trigger(void)
+{
+ cpu_state.smi_pending = 1;
+}
+
+static void smi_write_descriptor_cache(uint32_t addr, x86seg *seg)
+{
+ writememl(0, addr + 8, seg->seg | (seg->access << 16) | (seg->access2 << 24));
+ writememl(0, addr + 4, seg->base);
+ writememl(0, addr, seg->limit);
+}
+static void smi_load_descriptor_cache(uint32_t addr, x86seg *seg)
+{
+ uint32_t temp;
+
+ temp = readmeml(0, addr + 8);
+ seg->base = readmeml(0, addr + 4);
+ seg->limit = readmeml(0, addr);
+ seg->seg = temp & 0xffff;
+ seg->access = temp >> 16;
+ seg->access2 = temp >> 24;
+ if ((seg->access & 0x18) != 0x10 || !(seg->access & (1 << 2))) /*expand-down*/
+ {
+ seg->limit_high = seg->limit;
+ seg->limit_low = 0;
+ }
+ else
+ {
+ seg->limit_high = (seg->access2 & 0x40) ? 0xffffffff : 0xffff;
+ seg->limit_low = seg->limit + 1;
+ }
+}
+
+static void smi_load_smi_selector(x86seg *seg)
+{
+ seg->seg = 0;
+ seg->base = 0;
+ seg->limit = 0xffffffff;
+ seg->limit_low = 0;
+ seg->limit_high = 0xffffffff;
+ seg->access = (3 << 5) | 2;
+ seg->access2 = 0;
+}
+
+void cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg)
+{
+ writememl(0, addr, (seg->limit_raw & 0xffff) | (seg->base << 16));
+ writememl(0, addr+4, ((seg->base >> 16) & 0xff) |
+ (seg->access << 8) |
+ (seg->limit_raw & 0xf0000) |
+ (seg->access2 << 16) |
+ (seg->base & 0xff000000));
+}
+
+void cyrix_load_seg_descriptor(uint32_t addr, x86seg *seg)
+{
+ uint16_t segdat[4], selector;
+
+ segdat[0] = readmemw(0, addr);
+ segdat[1] = readmemw(0, addr+2);
+ segdat[2] = readmemw(0, addr+4);
+ segdat[3] = readmemw(0, addr+6);
+ selector = readmemw(0, addr+8);
+
+ if (!cpu_state.abrt)
+ {
+ do_seg_load(seg, segdat);
+ seg->seg = selector;
+ seg->checked = 0;
+ if (seg == &cpu_state.seg_ds)
+ {
+ if (seg->base == 0 && seg->limit_low == 0 && seg->limit_high == 0xffffffff)
+ cpu_cur_status &= ~CPU_STATUS_NOTFLATDS;
+ else
+ cpu_cur_status |= CPU_STATUS_NOTFLATDS;
+ codegen_flat_ds = 0;
+ }
+ if (seg == &cpu_state.seg_ss)
+ {
+ if (seg->base == 0 && seg->limit_low == 0 && seg->limit_high == 0xffffffff)
+ cpu_cur_status &= ~CPU_STATUS_NOTFLATSS;
+ else
+ cpu_cur_status |= CPU_STATUS_NOTFLATSS;
+ set_stack32((segdat[3] & 0x40) ? 1 : 0);
+ codegen_flat_ss = 0;
+ }
+ }
+}
+
+void x86_smi_enter(void)
+{
+ uint32_t old_cr0 = cr0;
+
+ if (smram_enable)
+ smram_enable();
+ flushmmucache();
+
+ cpu_386_flags_rebuild();
+ cpl_override = 1;
+ cr0 = 0; /*Disable MMU*/
+
+ if (cpu_iscyrix)
+ {
+ uint32_t base;
+
+ if (!(cyrix.smhr & SMHR_VALID))
+ cyrix.smhr = (cyrix.arr[3].base + cyrix.arr[3].size) | SMHR_VALID;
+ base = cyrix.smhr & SMHR_ADDR_MASK;
+
+ writememl(0, base-4, dr[7]);
+ writememl(0, base-8, cpu_state.flags | (cpu_state.eflags << 16));
+ writememl(0, base-0xc, old_cr0);
+ writememl(0, base-0x10, cpu_state.oldpc);
+ writememl(0, base-0x14, cpu_state.pc);
+ writememl(0, base-0x18, CS | (CPL << 21));
+ cyrix_write_seg_descriptor(base-0x20, &cpu_state.seg_cs);
+ writememl(0, base-0x24, 0);
+
+ cpl_override = 0;
+
+ cpu_cur_status = CPU_STATUS_SMM;
+ cpu_state.flags = 2;
+ cpu_state.eflags = 0;
+ cpu_state.pc = 0;
+ cr0 &= ~((1 << 0) | (1 << 2) | (1 << 3) | (1 << 31));
+ dr[7] = 0x400;
+ cpu_state.seg_cs.seg = cyrix.arr[3].base >> 4; /*Guess*/
+ cpu_state.seg_cs.base = cyrix.arr[3].base;
+ cpu_state.seg_cs.limit = 0xffffffff;
+ cpu_state.seg_cs.limit_low = 0;
+ cpu_state.seg_cs.limit_high = 0xffffffff;
+ cpu_state.seg_cs.access = (0 << 5) | 2;
+
+ use32 = 0;
+ stack32 = 0;
+ }
+ else
+ {
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7ffc, old_cr0);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7ff8, cr3);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7ff4, cpu_state.flags | (cpu_state.eflags << 16));
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7ff0, cpu_state.pc);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fec, EDI);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fe8, ESI);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fe4, EBP);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fe0, ESP);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fdc, EBX);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fd8, EDX);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fd4, ECX);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fd0, EAX);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fcc, dr[6]);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fc8, dr[7]);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fc4, tr.seg);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fc0, ldt.seg);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fbc, cpu_state.seg_gs.seg);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fb8, cpu_state.seg_fs.seg);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fb4, cpu_state.seg_ds.seg);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fb0, cpu_state.seg_ss.seg);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fac, cpu_state.seg_cs.seg);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7fa8, cpu_state.seg_es.seg);
+ smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f9c, &tr);
+ smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f90, &idt);
+ smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f84, &gdt);
+ smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f78, &ldt);
+ smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f6c, &cpu_state.seg_gs);
+ smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f60, &cpu_state.seg_fs);
+ smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f54, &cpu_state.seg_ds);
+ smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f48, &cpu_state.seg_ss);
+ smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f3c, &cpu_state.seg_cs);
+ smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f30, &cpu_state.seg_es);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7f28, cr4);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7ef8, cpu_state.smbase);
+ writememl(0, cpu_state.smbase + 0x8000 + 0x7efc, 0x00020000);
+ cpl_override = 0;
+
+ cpu_cur_status = CPU_STATUS_SMM;
+ cpu_state.flags = 2;
+ cpu_state.eflags = 0;
+ cpu_state.pc = 0x8000;
+ cr0 &= ~((1 << 0) | (1 << 2) | (1 << 3) | (1 << 31));
+ dr[7] = 0x400;
+ smi_load_smi_selector(&cpu_state.seg_ds);
+ smi_load_smi_selector(&cpu_state.seg_es);
+ smi_load_smi_selector(&cpu_state.seg_fs);
+ smi_load_smi_selector(&cpu_state.seg_gs);
+ smi_load_smi_selector(&cpu_state.seg_ss);
+ cpu_state.seg_cs.seg = 0x3000;
+ cpu_state.seg_cs.base = cpu_state.smbase;
+ cpu_state.seg_cs.limit = 0xffffffff;
+ cpu_state.seg_cs.limit_low = 0;
+ cpu_state.seg_cs.limit_high = 0xffffffff;
+ cpu_state.seg_cs.access = (0 << 5) | 2;
+
+ use32 = 0;
+ stack32 = 0;
+ }
+
+ oldcpl = 0;
+
+// pclog("x86_smi_enter\n");
+}
+
+void x86_smi_leave(void)
+{
+ uint32_t temp;
+ uint32_t new_cr0;
+
+ if (cpu_iscyrix)
+ {
+ uint32_t base = cyrix.smhr & SMHR_ADDR_MASK;
+
+ cpl_override = 1;
+ dr[7] = readmeml(0, base-4);
+ temp = readmeml(0, base-8);
+ cpu_state.flags = temp & 0xffff;
+ cpu_state.eflags = temp >> 16;
+ new_cr0 = readmeml(0, base-0xc);
+ cpu_state.pc = readmeml(0, base-0x14);
+ cyrix_load_seg_descriptor(base-0x20, &cpu_state.seg_cs);
+ cpl_override = 0;
+
+ cr0 = new_cr0;
+ }
+ else
+ {
+ cpl_override = 1;
+ new_cr0 = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ffc);
+ cr3 = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ff8);
+ temp = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ff4);
+ cpu_state.flags = temp & 0xffff;
+ cpu_state.eflags = temp >> 16;
+ cpu_state.pc = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ff0);
+ EDI = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fec);
+ ESI = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fe8);
+ EBP = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fe4);
+ ESP = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fe0);
+ EBX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fdc);
+ EDX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fd8);
+ ECX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fd4);
+ EAX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fd0);
+ dr[6] = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fcc);
+ dr[7] = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fc8);
+ tr.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fc4);
+ ldt.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fc0);
+ cpu_state.seg_gs.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fbc);
+ cpu_state.seg_fs.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fb8);
+ cpu_state.seg_ds.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fb4);
+ cpu_state.seg_ss.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fb0);
+ cpu_state.seg_cs.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fac);
+ cpu_state.seg_es.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fa8);
+ smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f9c, &tr);
+ smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f90, &idt);
+ smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f84, &gdt);
+ smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f78, &ldt);
+ smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f6c, &cpu_state.seg_gs);
+ smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f60, &cpu_state.seg_fs);
+ smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f54, &cpu_state.seg_ds);
+ smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f48, &cpu_state.seg_ss);
+ smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f3c, &cpu_state.seg_cs);
+ smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f30, &cpu_state.seg_es);
+ cr4 = readmeml(0, cpu_state.smbase + 0x8000 + 0x7f28);
+ cpu_state.smbase = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ef8);
+ cpl_override = 0;
+
+ cr0 = new_cr0;
+ }
+
+ cpu_386_flags_extract();
+ cpu_cur_status = 0;
+ use32 = stack32 = 0;
+ if (cr0 & 1)
+ {
+ cpu_cur_status |= CPU_STATUS_PMODE;
+ if (cpu_state.eflags & VM_FLAG)
+ cpu_cur_status |= CPU_STATUS_V86;
+ else
+ {
+ if (cpu_state.seg_cs.access2 & 0x40)
+ {
+ cpu_cur_status |= CPU_STATUS_USE32;
+ use32 = 0x300;
+ }
+ if (cpu_state.seg_ss.access2 & 0x40)
+ {
+ cpu_cur_status |= CPU_STATUS_STACK32;
+ stack32 = 1;
+ }
+ }
+ }
+ if (!(cpu_state.seg_ds.base == 0 && cpu_state.seg_ds.limit_low == 0 && cpu_state.seg_ds.limit_high == 0xffffffff))
+ cpu_cur_status |= CPU_STATUS_NOTFLATDS;
+ if (!(cpu_state.seg_ss.base == 0 && cpu_state.seg_ss.limit_low == 0 && cpu_state.seg_ss.limit_high == 0xffffffff))
+ cpu_cur_status |= CPU_STATUS_NOTFLATSS;
+
+ if (smram_disable)
+ smram_disable();
+ flushmmucache();
+
+ oldcpl = CPL;
+
+// pclog("x86_smi_leave\n");
+}
diff --git a/src/x87.c b/src/x87.c
index 44f22e0..ac2650d 100644
--- a/src/x87.c
+++ b/src/x87.c
@@ -35,7 +35,7 @@ uint16_t x87_gettag()
ret |= X87_TAG_EMPTY << (c * 2);
else if (cpu_state.tag[c] & TAG_UINT64)
ret |= 2 << (c*2);
- else if (cpu_state.ST[c] == 0.0)
+ else if (cpu_state.ST[c] == 0.0 && !cpu_state.ismmx)
ret |= X87_TAG_ZERO << (c * 2);
else
ret |= X87_TAG_VALID << (c * 2);
diff --git a/src/x87.h b/src/x87.h
index 2ec4405..9441a41 100644
--- a/src/x87.h
+++ b/src/x87.h
@@ -9,7 +9,7 @@ uint16_t x87_pc_seg,x87_op_seg;
static inline void x87_set_mmx()
{
cpu_state.TOP = 0;
- *(uint64_t *)cpu_state.tag = 0;
+ *(uint64_t *)cpu_state.tag = 0x0101010101010101ull;
cpu_state.ismmx = 1;
}
diff --git a/src/x87_ops.h b/src/x87_ops.h
index 1208854..361dcb7 100644
--- a/src/x87_ops.h
+++ b/src/x87_ops.h
@@ -1,5 +1,6 @@
#include
#include
+#include "x87_timings.h"
#define fplog 0
@@ -9,6 +10,8 @@ static int rounding_modes[4] = {FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZ
#define STATUS_ZERODIVIDE 4
+#define FPCW_DISI (1 << 7)
+
#define x87_div(dst, src1, src2) do \
{ \
if (((double)src2) == 0.0) \
@@ -187,7 +190,7 @@ static inline void x87_ld_frstor(int reg)
}
else
{
- cpu_state.tag[reg] = TAG_VALID;
+ cpu_state.tag[reg] &= ~TAG_UINT64;
cpu_state.ST[reg] = x87_ld80();
}
}
@@ -208,7 +211,7 @@ static inline void x87_stmmx(MMX_REG r)
static inline uint16_t x87_compare(double a, double b)
{
-#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
+#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 || defined __amd64__
uint32_t out;
/* Memory barrier, to force GCC to write to the input parameters
@@ -242,7 +245,7 @@ static inline uint16_t x87_compare(double a, double b)
static inline uint16_t x87_ucompare(double a, double b)
{
-#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
+#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 || defined __amd64__
uint32_t out;
/* Memory barrier, to force GCC to write to the input parameters
@@ -286,6 +289,9 @@ typedef union
uint64_t i;
} x87_td;
+#ifdef X8087
+#define FP_ENTER() fpucount++
+#else
#define FP_ENTER() do \
{ \
if (cr0 & 0xc) \
@@ -295,6 +301,7 @@ typedef union
} \
fpucount++; \
} while (0)
+#endif
#include "x87_ops_arith.h"
#include "x87_ops_misc.h"
@@ -634,7 +641,7 @@ OpFn OP_TABLE(fpu_db_a16)[256] =
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
- ILLEGAL, opFNOP, opFCLEX, opFINIT, opFNOP, opFNOP, ILLEGAL, ILLEGAL,
+ opFENI, opFDISI, opFCLEX, opFINIT, opFNOP, opFNOP, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -674,7 +681,7 @@ OpFn OP_TABLE(fpu_db_a32)[256] =
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
- ILLEGAL, opFNOP, opFCLEX, opFINIT, opFNOP, opFNOP, ILLEGAL, ILLEGAL,
+ opFENI, opFDISI, opFCLEX, opFINIT, opFNOP, opFNOP, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
diff --git a/src/x87_ops_arith.h b/src/x87_ops_arith.h
index f52abe8..cf8d1ae 100644
--- a/src/x87_ops_arith.h
+++ b/src/x87_ops_arith.h
@@ -1,4 +1,4 @@
-#define opFPU(name, optype, a_size, load_var, get, use_var) \
+#define opFPU(name, optype, a_size, load_var, get, use_var, cycle_postfix) \
static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \
{ \
optype t; \
@@ -12,7 +12,7 @@ static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \
if ((cpu_state.npxc >> 10) & 3) \
fesetround(FE_TONEAREST); \
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
- CLOCK_CYCLES(8); \
+ CLOCK_CYCLES(x87_timings.fadd ## cycle_postfix); \
return 0; \
} \
static int opFCOM ## name ## _a ## a_size(uint32_t fetchdat) \
@@ -24,7 +24,7 @@ static int opFCOM ## name ## _a ## a_size(uint32_t fetchdat) \
load_var = get(); if (cpu_state.abrt) return 1; \
cpu_state.npxs &= ~(C0|C2|C3); \
cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \
- CLOCK_CYCLES(4); \
+ CLOCK_CYCLES(x87_timings.fcom ## cycle_postfix); \
return 0; \
} \
static int opFCOMP ## name ## _a ## a_size(uint32_t fetchdat) \
@@ -37,7 +37,7 @@ static int opFCOMP ## name ## _a ## a_size(uint32_t fetchdat) \
cpu_state.npxs &= ~(C0|C2|C3); \
cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \
x87_pop(); \
- CLOCK_CYCLES(4); \
+ CLOCK_CYCLES(x87_timings.fcom ## cycle_postfix); \
return 0; \
} \
static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \
@@ -49,7 +49,7 @@ static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \
load_var = get(); if (cpu_state.abrt) return 1; \
x87_div(ST(0), ST(0), use_var); \
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
- CLOCK_CYCLES(73); \
+ CLOCK_CYCLES(x87_timings.fdiv ## cycle_postfix); \
return 0; \
} \
static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \
@@ -61,7 +61,7 @@ static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \
load_var = get(); if (cpu_state.abrt) return 1; \
x87_div(ST(0), use_var, ST(0)); \
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
- CLOCK_CYCLES(73); \
+ CLOCK_CYCLES(x87_timings.fdiv ## cycle_postfix); \
return 0; \
} \
static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \
@@ -73,7 +73,7 @@ static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \
load_var = get(); if (cpu_state.abrt) return 1; \
ST(0) *= use_var; \
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
- CLOCK_CYCLES(11); \
+ CLOCK_CYCLES(x87_timings.fmul ## cycle_postfix); \
return 0; \
} \
static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \
@@ -85,7 +85,7 @@ static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \
load_var = get(); if (cpu_state.abrt) return 1; \
ST(0) -= use_var; \
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
- CLOCK_CYCLES(8); \
+ CLOCK_CYCLES(x87_timings.fadd ## cycle_postfix); \
return 0; \
} \
static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \
@@ -97,20 +97,20 @@ static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \
load_var = get(); if (cpu_state.abrt) return 1; \
ST(0) = use_var - ST(0); \
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
- CLOCK_CYCLES(8); \
+ CLOCK_CYCLES(x87_timings.fadd ## cycle_postfix); \
return 0; \
}
-opFPU(s, x87_ts, 16, t.i, geteal, t.s)
-opFPU(s, x87_ts, 32, t.i, geteal, t.s)
-opFPU(d, x87_td, 16, t.i, geteaq, t.d)
-opFPU(d, x87_td, 32, t.i, geteaq, t.d)
+opFPU(s, x87_ts, 16, t.i, geteal, t.s, _32)
+opFPU(s, x87_ts, 32, t.i, geteal, t.s, _32)
+opFPU(d, x87_td, 16, t.i, geteaq, t.d, _64)
+opFPU(d, x87_td, 32, t.i, geteaq, t.d, _64)
-opFPU(iw, uint16_t, 16, t, geteaw, (double)(int16_t)t)
-opFPU(iw, uint16_t, 32, t, geteaw, (double)(int16_t)t)
-opFPU(il, uint32_t, 16, t, geteal, (double)(int32_t)t)
-opFPU(il, uint32_t, 32, t, geteal, (double)(int32_t)t)
+opFPU(iw, uint16_t, 16, t, geteaw, (double)(int16_t)t, _i16)
+opFPU(iw, uint16_t, 32, t, geteaw, (double)(int16_t)t, _i16)
+opFPU(il, uint32_t, 16, t, geteal, (double)(int32_t)t, _i32)
+opFPU(il, uint32_t, 32, t, geteal, (double)(int32_t)t, _i32)
@@ -122,7 +122,7 @@ static int opFADD(uint32_t fetchdat)
if (fplog) pclog("FADD\n");
ST(0) = ST(0) + ST(fetchdat & 7);
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
static int opFADDr(uint32_t fetchdat)
@@ -132,7 +132,7 @@ static int opFADDr(uint32_t fetchdat)
if (fplog) pclog("FADD\n");
ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0);
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
static int opFADDP(uint32_t fetchdat)
@@ -143,7 +143,7 @@ static int opFADDP(uint32_t fetchdat)
ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0);
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
@@ -155,7 +155,7 @@ static int opFCOM(uint32_t fetchdat)
cpu_state.npxs &= ~(C0|C2|C3);
if (ST(0) == ST(fetchdat & 7)) cpu_state.npxs |= C3;
else if (ST(0) < ST(fetchdat & 7)) cpu_state.npxs |= C0;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
@@ -167,7 +167,7 @@ static int opFCOMP(uint32_t fetchdat)
cpu_state.npxs &= ~(C0|C2|C3);
cpu_state.npxs |= x87_compare(ST(0), ST(fetchdat & 7));
x87_pop();
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
@@ -184,7 +184,7 @@ static int opFCOMPP(uint32_t fetchdat)
x87_pop();
x87_pop();
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
static int opFUCOMPP(uint32_t fetchdat)
@@ -196,7 +196,7 @@ static int opFUCOMPP(uint32_t fetchdat)
cpu_state.npxs |= x87_ucompare(ST(0), ST(1));
x87_pop();
x87_pop();
- CLOCK_CYCLES(5);
+ CLOCK_CYCLES(x87_timings.fucom);
return 0;
}
@@ -209,7 +209,7 @@ static int opFCOMI(uint32_t fetchdat)
cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG);
if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG;
else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fcom);
return 0;
}
static int opFCOMIP(uint32_t fetchdat)
@@ -222,7 +222,7 @@ static int opFCOMIP(uint32_t fetchdat)
if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG;
else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG;
x87_pop();
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fcom);
return 0;
}
@@ -233,7 +233,7 @@ static int opFDIV(uint32_t fetchdat)
if (fplog) pclog("FDIV\n");
x87_div(ST(0), ST(0), ST(fetchdat & 7));
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
- CLOCK_CYCLES(73);
+ CLOCK_CYCLES(x87_timings.fdiv);
return 0;
}
static int opFDIVr(uint32_t fetchdat)
@@ -243,7 +243,7 @@ static int opFDIVr(uint32_t fetchdat)
if (fplog) pclog("FDIV\n");
x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0));
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
- CLOCK_CYCLES(73);
+ CLOCK_CYCLES(x87_timings.fdiv);
return 0;
}
static int opFDIVP(uint32_t fetchdat)
@@ -254,7 +254,7 @@ static int opFDIVP(uint32_t fetchdat)
x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0));
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(73);
+ CLOCK_CYCLES(x87_timings.fdiv);
return 0;
}
@@ -265,7 +265,7 @@ static int opFDIVR(uint32_t fetchdat)
if (fplog) pclog("FDIVR\n");
x87_div(ST(0), ST(fetchdat&7), ST(0));
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
- CLOCK_CYCLES(73);
+ CLOCK_CYCLES(x87_timings.fdiv);
return 0;
}
static int opFDIVRr(uint32_t fetchdat)
@@ -275,7 +275,7 @@ static int opFDIVRr(uint32_t fetchdat)
if (fplog) pclog("FDIVR\n");
x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7));
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
- CLOCK_CYCLES(73);
+ CLOCK_CYCLES(x87_timings.fdiv);
return 0;
}
static int opFDIVRP(uint32_t fetchdat)
@@ -286,7 +286,7 @@ static int opFDIVRP(uint32_t fetchdat)
x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7));
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(73);
+ CLOCK_CYCLES(x87_timings.fdiv);
return 0;
}
@@ -297,7 +297,7 @@ static int opFMUL(uint32_t fetchdat)
if (fplog) pclog("FMUL\n");
ST(0) = ST(0) * ST(fetchdat & 7);
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
- CLOCK_CYCLES(16);
+ CLOCK_CYCLES(x87_timings.fmul);
return 0;
}
static int opFMULr(uint32_t fetchdat)
@@ -307,7 +307,7 @@ static int opFMULr(uint32_t fetchdat)
if (fplog) pclog("FMUL\n");
ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7);
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
- CLOCK_CYCLES(16);
+ CLOCK_CYCLES(x87_timings.fmul);
return 0;
}
static int opFMULP(uint32_t fetchdat)
@@ -318,7 +318,7 @@ static int opFMULP(uint32_t fetchdat)
ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7);
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(16);
+ CLOCK_CYCLES(x87_timings.fmul);
return 0;
}
@@ -329,7 +329,7 @@ static int opFSUB(uint32_t fetchdat)
if (fplog) pclog("FSUB\n");
ST(0) = ST(0) - ST(fetchdat & 7);
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
static int opFSUBr(uint32_t fetchdat)
@@ -339,7 +339,7 @@ static int opFSUBr(uint32_t fetchdat)
if (fplog) pclog("FSUB\n");
ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0);
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
static int opFSUBP(uint32_t fetchdat)
@@ -350,7 +350,7 @@ static int opFSUBP(uint32_t fetchdat)
ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0);
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
@@ -361,7 +361,7 @@ static int opFSUBR(uint32_t fetchdat)
if (fplog) pclog("FSUBR\n");
ST(0) = ST(fetchdat & 7) - ST(0);
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
static int opFSUBRr(uint32_t fetchdat)
@@ -371,7 +371,7 @@ static int opFSUBRr(uint32_t fetchdat)
if (fplog) pclog("FSUBR\n");
ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7);
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
static int opFSUBRP(uint32_t fetchdat)
@@ -382,7 +382,7 @@ static int opFSUBRP(uint32_t fetchdat)
ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7);
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
@@ -393,7 +393,7 @@ static int opFUCOM(uint32_t fetchdat)
if (fplog) pclog("FUCOM\n");
cpu_state.npxs &= ~(C0|C2|C3);
cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7));
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fucom);
return 0;
}
@@ -405,7 +405,7 @@ static int opFUCOMP(uint32_t fetchdat)
cpu_state.npxs &= ~(C0|C2|C3);
cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7));
x87_pop();
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fucom);
return 0;
}
@@ -418,7 +418,7 @@ static int opFUCOMI(uint32_t fetchdat)
cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG);
if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG;
else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fucom);
return 0;
}
static int opFUCOMIP(uint32_t fetchdat)
@@ -431,6 +431,6 @@ static int opFUCOMIP(uint32_t fetchdat)
if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG;
else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG;
x87_pop();
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fucom);
return 0;
}
diff --git a/src/x87_ops_loadstore.h b/src/x87_ops_loadstore.h
index 96c18e6..6c61b7f 100644
--- a/src/x87_ops_loadstore.h
+++ b/src/x87_ops_loadstore.h
@@ -8,7 +8,7 @@ static int opFILDiw_a16(uint32_t fetchdat)
temp = geteaw(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", (double)temp);
x87_push((double)temp);
- CLOCK_CYCLES(13);
+ CLOCK_CYCLES(x87_timings.fild_16);
return 0;
}
static int opFILDiw_a32(uint32_t fetchdat)
@@ -21,7 +21,7 @@ static int opFILDiw_a32(uint32_t fetchdat)
temp = geteaw(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", (double)temp);
x87_push((double)temp);
- CLOCK_CYCLES(13);
+ CLOCK_CYCLES(x87_timings.fild_16);
return 0;
}
@@ -36,7 +36,7 @@ static int opFISTiw_a16(uint32_t fetchdat)
/* if (temp64 > 32767 || temp64 < -32768)
fatal("FISTw overflow %i\n", temp64);*/
seteaw((int16_t)temp64);
- CLOCK_CYCLES(29);
+ CLOCK_CYCLES(x87_timings.fist_16);
return cpu_state.abrt;
}
static int opFISTiw_a32(uint32_t fetchdat)
@@ -50,7 +50,7 @@ static int opFISTiw_a32(uint32_t fetchdat)
/* if (temp64 > 32767 || temp64 < -32768)
fatal("FISTw overflow %i\n", temp64);*/
seteaw((int16_t)temp64);
- CLOCK_CYCLES(29);
+ CLOCK_CYCLES(x87_timings.fist_16);
return cpu_state.abrt;
}
@@ -66,7 +66,7 @@ static int opFISTPiw_a16(uint32_t fetchdat)
fatal("FISTw overflow %i\n", temp64);*/
seteaw((int16_t)temp64); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(29);
+ CLOCK_CYCLES(x87_timings.fist_16);
return 0;
}
static int opFISTPiw_a32(uint32_t fetchdat)
@@ -81,7 +81,7 @@ static int opFISTPiw_a32(uint32_t fetchdat)
fatal("FISTw overflow %i\n", temp64);*/
seteaw((int16_t)temp64); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(29);
+ CLOCK_CYCLES(x87_timings.fist_16);
return 0;
}
@@ -98,7 +98,7 @@ static int opFILDiq_a16(uint32_t fetchdat)
cpu_state.MM[cpu_state.TOP&7].q = temp64;
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64;
- CLOCK_CYCLES(10);
+ CLOCK_CYCLES(x87_timings.fild_64);
return 0;
}
static int opFILDiq_a32(uint32_t fetchdat)
@@ -114,7 +114,7 @@ static int opFILDiq_a32(uint32_t fetchdat)
cpu_state.MM[cpu_state.TOP&7].q = temp64;
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64;
- CLOCK_CYCLES(10);
+ CLOCK_CYCLES(x87_timings.fild_64);
return 0;
}
@@ -143,6 +143,7 @@ static int FBSTP_a16(uint32_t fetchdat)
if (ST(0) < 0.0) tempc |= 0x80;
writememb(easeg, cpu_state.eaaddr + 9, tempc); if (cpu_state.abrt) return 1;
x87_pop();
+ CLOCK_CYCLES(x87_timings.fbstp);
return 0;
}
static int FBSTP_a32(uint32_t fetchdat)
@@ -170,6 +171,7 @@ static int FBSTP_a32(uint32_t fetchdat)
if (ST(0) < 0.0) tempc |= 0x80;
writememb(easeg, cpu_state.eaaddr + 9, tempc); if (cpu_state.abrt) return 1;
x87_pop();
+ CLOCK_CYCLES(x87_timings.fbstp);
return 0;
}
@@ -186,7 +188,7 @@ static int FISTPiq_a16(uint32_t fetchdat)
temp64 = x87_fround(ST(0));
seteaq(temp64); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(29);
+ CLOCK_CYCLES(x87_timings.fist_64);
return 0;
}
static int FISTPiq_a32(uint32_t fetchdat)
@@ -202,7 +204,7 @@ static int FISTPiq_a32(uint32_t fetchdat)
temp64 = x87_fround(ST(0));
seteaq(temp64); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(29);
+ CLOCK_CYCLES(x87_timings.fist_64);
return 0;
}
@@ -216,7 +218,7 @@ static int opFILDil_a16(uint32_t fetchdat)
templ = geteal(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f %08X %i\n", (double)templ, templ, templ);
x87_push((double)templ);
- CLOCK_CYCLES(9);
+ CLOCK_CYCLES(x87_timings.fild_32);
return 0;
}
static int opFILDil_a32(uint32_t fetchdat)
@@ -229,7 +231,7 @@ static int opFILDil_a32(uint32_t fetchdat)
templ = geteal(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f %08X %i\n", (double)templ, templ, templ);
x87_push((double)templ);
- CLOCK_CYCLES(9);
+ CLOCK_CYCLES(x87_timings.fild_32);
return 0;
}
@@ -244,7 +246,7 @@ static int opFISTil_a16(uint32_t fetchdat)
/* if (temp64 > 2147483647 || temp64 < -2147483647)
fatal("FISTl out of range! %i\n", temp64);*/
seteal((int32_t)temp64);
- CLOCK_CYCLES(28);
+ CLOCK_CYCLES(x87_timings.fist_32);
return cpu_state.abrt;
}
static int opFISTil_a32(uint32_t fetchdat)
@@ -258,7 +260,7 @@ static int opFISTil_a32(uint32_t fetchdat)
/* if (temp64 > 2147483647 || temp64 < -2147483647)
fatal("FISTl out of range! %i\n", temp64);*/
seteal((int32_t)temp64);
- CLOCK_CYCLES(28);
+ CLOCK_CYCLES(x87_timings.fist_32);
return cpu_state.abrt;
}
@@ -274,7 +276,7 @@ static int opFISTPil_a16(uint32_t fetchdat)
fatal("FISTl out of range! %i\n", temp64);*/
seteal((int32_t)temp64); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(28);
+ CLOCK_CYCLES(x87_timings.fist_32);
return 0;
}
static int opFISTPil_a32(uint32_t fetchdat)
@@ -289,7 +291,7 @@ static int opFISTPil_a32(uint32_t fetchdat)
fatal("FISTl out of range! %i\n", temp64);*/
seteal((int32_t)temp64); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(28);
+ CLOCK_CYCLES(x87_timings.fist_32);
return 0;
}
@@ -303,7 +305,7 @@ static int opFLDe_a16(uint32_t fetchdat)
t=x87_ld80(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", t);
x87_push(t);
- CLOCK_CYCLES(6);
+ CLOCK_CYCLES(x87_timings.fld_80);
return 0;
}
static int opFLDe_a32(uint32_t fetchdat)
@@ -316,7 +318,7 @@ static int opFLDe_a32(uint32_t fetchdat)
t=x87_ld80(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", t);
x87_push(t);
- CLOCK_CYCLES(6);
+ CLOCK_CYCLES(x87_timings.fld_80);
return 0;
}
@@ -328,7 +330,7 @@ static int opFSTPe_a16(uint32_t fetchdat)
if (fplog) pclog("FSTPe %08X:%08X\n", easeg, cpu_state.eaaddr);
x87_st80(ST(0)); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(6);
+ CLOCK_CYCLES(x87_timings.fst_80);
return 0;
}
static int opFSTPe_a32(uint32_t fetchdat)
@@ -339,7 +341,7 @@ static int opFSTPe_a32(uint32_t fetchdat)
if (fplog) pclog("FSTPe %08X:%08X\n", easeg, cpu_state.eaaddr);
x87_st80(ST(0)); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(6);
+ CLOCK_CYCLES(x87_timings.fst_80);
return 0;
}
@@ -353,7 +355,7 @@ static int opFLDd_a16(uint32_t fetchdat)
t.i = geteaq(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", t.d);
x87_push(t.d);
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fld_64);
return 0;
}
static int opFLDd_a32(uint32_t fetchdat)
@@ -366,7 +368,7 @@ static int opFLDd_a32(uint32_t fetchdat)
t.i = geteaq(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", t.d);
x87_push(t.d);
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fld_64);
return 0;
}
@@ -379,7 +381,7 @@ static int opFSTd_a16(uint32_t fetchdat)
if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr);
t.d = ST(0);
seteaq(t.i);
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fst_64);
return cpu_state.abrt;
}
static int opFSTd_a32(uint32_t fetchdat)
@@ -391,7 +393,7 @@ static int opFSTd_a32(uint32_t fetchdat)
if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr);
t.d = ST(0);
seteaq(t.i);
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fst_64);
return cpu_state.abrt;
}
@@ -406,7 +408,7 @@ static int opFSTPd_a16(uint32_t fetchdat)
t.d = ST(0);
seteaq(t.i); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fst_64);
return 0;
}
static int opFSTPd_a32(uint32_t fetchdat)
@@ -420,7 +422,7 @@ static int opFSTPd_a32(uint32_t fetchdat)
t.d = ST(0);
seteaq(t.i); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fst_64);
return 0;
}
@@ -434,7 +436,7 @@ static int opFLDs_a16(uint32_t fetchdat)
ts.i = geteal(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", ts.s);
x87_push((double)ts.s);
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fld_32);
return 0;
}
static int opFLDs_a32(uint32_t fetchdat)
@@ -447,7 +449,7 @@ static int opFLDs_a32(uint32_t fetchdat)
ts.i = geteal(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", ts.s);
x87_push((double)ts.s);
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fld_32);
return 0;
}
@@ -460,7 +462,7 @@ static int opFSTs_a16(uint32_t fetchdat)
if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr);
ts.s = (float)ST(0);
seteal(ts.i);
- CLOCK_CYCLES(7);
+ CLOCK_CYCLES(x87_timings.fst_32);
return cpu_state.abrt;
}
static int opFSTs_a32(uint32_t fetchdat)
@@ -472,7 +474,7 @@ static int opFSTs_a32(uint32_t fetchdat)
if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr);
ts.s = (float)ST(0);
seteal(ts.i);
- CLOCK_CYCLES(7);
+ CLOCK_CYCLES(x87_timings.fst_32);
return cpu_state.abrt;
}
@@ -486,7 +488,7 @@ static int opFSTPs_a16(uint32_t fetchdat)
ts.s = (float)ST(0);
seteal(ts.i); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(7);
+ CLOCK_CYCLES(x87_timings.fst_32);
return 0;
}
static int opFSTPs_a32(uint32_t fetchdat)
@@ -499,6 +501,6 @@ static int opFSTPs_a32(uint32_t fetchdat)
ts.s = (float)ST(0);
seteal(ts.i); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(7);
+ CLOCK_CYCLES(x87_timings.fst_32);
return 0;
}
diff --git a/src/x87_ops_misc.h b/src/x87_ops_misc.h
index f22d618..8abb544 100644
--- a/src/x87_ops_misc.h
+++ b/src/x87_ops_misc.h
@@ -1,10 +1,37 @@
+static int opFDISI(uint32_t fetchdat)
+{
+ FP_ENTER();
+ cpu_state.pc++;
+ if (fpu_type == FPU_8087)
+ {
+ cpu_state.npxc |= FPCW_DISI;
+ CLOCK_CYCLES(x87_timings.fdisi_eni);
+ }
+ else
+ CLOCK_CYCLES(x87_timings.fnop);
+ return 0;
+}
+static int opFENI(uint32_t fetchdat)
+{
+ FP_ENTER();
+ cpu_state.pc++;
+ if (fpu_type == FPU_8087)
+ {
+ cpu_state.npxc &= ~FPCW_DISI;
+ CLOCK_CYCLES(x87_timings.fdisi_eni);
+ }
+ else
+ CLOCK_CYCLES(x87_timings.fnop);
+ return 0;
+}
+
static int opFSTSW_AX(uint32_t fetchdat)
{
FP_ENTER();
cpu_state.pc++;
if (fplog) pclog("FSTSW\n");
AX = cpu_state.npxs;
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fstcw_sw);
return 0;
}
@@ -14,7 +41,7 @@ static int opFNOP(uint32_t fetchdat)
{
FP_ENTER();
cpu_state.pc++;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fnop);
return 0;
}
@@ -23,7 +50,7 @@ static int opFCLEX(uint32_t fetchdat)
FP_ENTER();
cpu_state.pc++;
cpu_state.npxs &= 0xff00;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fclex);
return 0;
}
@@ -31,13 +58,16 @@ static int opFINIT(uint32_t fetchdat)
{
FP_ENTER();
cpu_state.pc++;
- cpu_state.npxc = 0x37F;
+ if (fpu_type == FPU_8087)
+ cpu_state.npxc = 0x3ff;
+ else
+ cpu_state.npxc = 0x37f;
codegen_set_rounding_mode(X87_ROUNDING_NEAREST);
cpu_state.npxs = 0;
*(uint64_t *)cpu_state.tag = 0;
cpu_state.TOP = 0;
cpu_state.ismmx = 0;
- CLOCK_CYCLES(17);
+ CLOCK_CYCLES(x87_timings.finit);
CPU_BLOCK_END();
return 0;
}
@@ -49,7 +79,7 @@ static int opFFREE(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FFREE\n");
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_EMPTY;
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.ffree);
return 0;
}
@@ -60,7 +90,7 @@ static int opFST(uint32_t fetchdat)
if (fplog) pclog("FST\n");
ST(fetchdat & 7) = ST(0);
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7];
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fst);
return 0;
}
@@ -72,7 +102,7 @@ static int opFSTP(uint32_t fetchdat)
ST(fetchdat & 7) = ST(0);
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7];
x87_pop();
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fst);
return 0;
}
@@ -117,10 +147,10 @@ static int FSTOR()
something like this is needed*/
if (cpu_state.MM_w4[0] == 0xffff && cpu_state.MM_w4[1] == 0xffff && cpu_state.MM_w4[2] == 0xffff && cpu_state.MM_w4[3] == 0xffff &&
cpu_state.MM_w4[4] == 0xffff && cpu_state.MM_w4[5] == 0xffff && cpu_state.MM_w4[6] == 0xffff && cpu_state.MM_w4[7] == 0xffff &&
- !cpu_state.TOP && !(*(uint64_t *)cpu_state.tag))
- cpu_state.ismmx = 1;
+ !cpu_state.TOP && (*(uint64_t *)cpu_state.tag == 0x0101010101010101ull))
+ cpu_state.ismmx = 1;
- CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
+ CLOCK_CYCLES(x87_timings.frstor);
if (fplog) pclog("FRSTOR %08X:%08X %i %i %04X\n", easeg, cpu_state.eaaddr, cpu_state.ismmx, cpu_state.TOP, x87_gettag());
return cpu_state.abrt;
}
@@ -283,7 +313,7 @@ static int FSAVE()
cpu_state.TOP = 0;
cpu_state.ismmx = 0;
- CLOCK_CYCLES((cr0 & 1) ? 56 : 67);
+ CLOCK_CYCLES(x87_timings.fsave);
return cpu_state.abrt;
}
static int opFSAVE_a16(uint32_t fetchdat)
@@ -310,7 +340,7 @@ static int opFSTSW_a16(uint32_t fetchdat)
SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr);
seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11));
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fstcw_sw);
return cpu_state.abrt;
}
static int opFSTSW_a32(uint32_t fetchdat)
@@ -320,7 +350,7 @@ static int opFSTSW_a32(uint32_t fetchdat)
SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr);
seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11));
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fstcw_sw);
return cpu_state.abrt;
}
@@ -338,7 +368,7 @@ static int opFLD(uint32_t fetchdat)
x87_push(ST(fetchdat&7));
cpu_state.tag[cpu_state.TOP&7] = old_tag;
cpu_state.MM[cpu_state.TOP&7].q = old_i64;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fld);
return 0;
}
@@ -360,7 +390,7 @@ static int opFXCH(uint32_t fetchdat)
cpu_state.MM[cpu_state.TOP&7].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q;
cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q = old_i64;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fxch);
return 0;
}
@@ -371,7 +401,7 @@ static int opFCHS(uint32_t fetchdat)
if (fplog) pclog("FCHS\n");
ST(0) = -ST(0);
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
- CLOCK_CYCLES(6);
+ CLOCK_CYCLES(x87_timings.fchs);
return 0;
}
@@ -382,7 +412,7 @@ static int opFABS(uint32_t fetchdat)
if (fplog) pclog("FABS %f\n", ST(0));
ST(0) = fabs(ST(0));
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fabs);
return 0;
}
@@ -394,7 +424,7 @@ static int opFTST(uint32_t fetchdat)
cpu_state.npxs &= ~(C0|C2|C3);
if (ST(0) == 0.0) cpu_state.npxs |= C3;
else if (ST(0) < 0.0) cpu_state.npxs |= C0;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.ftst);
return 0;
}
@@ -408,7 +438,7 @@ static int opFXAM(uint32_t fetchdat)
else if (ST(0) == 0.0) cpu_state.npxs |= C3;
else cpu_state.npxs |= C2;
if (ST(0) < 0.0) cpu_state.npxs |= C1;
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fxam);
return 0;
}
@@ -418,7 +448,7 @@ static int opFLD1(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FLD1\n");
x87_push(1.0);
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fld_z1);
return 0;
}
@@ -428,7 +458,7 @@ static int opFLDL2T(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FLDL2T\n");
x87_push(3.3219280948873623);
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fld_const);
return 0;
}
@@ -438,7 +468,7 @@ static int opFLDL2E(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FLDL2E\n");
x87_push(1.4426950408889634);
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fld_const);
return 0;
}
@@ -448,7 +478,7 @@ static int opFLDPI(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FLDPI\n");
x87_push(3.141592653589793);
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fld_const);
return 0;
}
@@ -458,7 +488,7 @@ static int opFLDEG2(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FLDEG2\n");
x87_push(0.3010299956639812);
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fld_const);
return 0;
}
@@ -468,7 +498,7 @@ static int opFLDLN2(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FLDLN2\n");
x87_push_u64(0x3fe62e42fefa39f0ull);
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fld_const);
return 0;
}
@@ -479,7 +509,7 @@ static int opFLDZ(uint32_t fetchdat)
if (fplog) pclog("FLDZ\n");
x87_push(0.0);
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fld_z1);
return 0;
}
@@ -490,7 +520,7 @@ static int opF2XM1(uint32_t fetchdat)
if (fplog) pclog("F2XM1\n");
ST(0) = pow(2.0, ST(0)) - 1.0;
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
- CLOCK_CYCLES(200);
+ CLOCK_CYCLES(x87_timings.f2xm1);
return 0;
}
@@ -502,7 +532,7 @@ static int opFYL2X(uint32_t fetchdat)
ST(1) = ST(1) * (log(ST(0)) / log(2.0));
cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(250);
+ CLOCK_CYCLES(x87_timings.fyl2x);
return 0;
}
@@ -514,7 +544,7 @@ static int opFYL2XP1(uint32_t fetchdat)
ST(1) = ST(1) * (log(ST(0)+1.0) / log(2.0));
cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(250);
+ CLOCK_CYCLES(x87_timings.fyl2xp1);
return 0;
}
@@ -527,7 +557,7 @@ static int opFPTAN(uint32_t fetchdat)
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
x87_push(1.0);
cpu_state.npxs &= ~C2;
- CLOCK_CYCLES(235);
+ CLOCK_CYCLES(x87_timings.fptan);
return 0;
}
@@ -539,7 +569,7 @@ static int opFPATAN(uint32_t fetchdat)
ST(1) = atan2(ST(1), ST(0));
cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(250);
+ CLOCK_CYCLES(x87_timings.fpatan);
return 0;
}
@@ -549,7 +579,7 @@ static int opFDECSTP(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FDECSTP\n");
cpu_state.TOP--;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fincdecstp);
return 0;
}
@@ -559,7 +589,7 @@ static int opFINCSTP(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FDECSTP\n");
cpu_state.TOP++;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fincdecstp);
return 0;
}
@@ -577,7 +607,7 @@ static int opFPREM(uint32_t fetchdat)
if (temp64 & 4) cpu_state.npxs|=C0;
if (temp64 & 2) cpu_state.npxs|=C3;
if (temp64 & 1) cpu_state.npxs|=C1;
- CLOCK_CYCLES(100);
+ CLOCK_CYCLES(x87_timings.fprem);
return 0;
}
static int opFPREM1(uint32_t fetchdat)
@@ -594,7 +624,7 @@ static int opFPREM1(uint32_t fetchdat)
if (temp64 & 4) cpu_state.npxs|=C0;
if (temp64 & 2) cpu_state.npxs|=C3;
if (temp64 & 1) cpu_state.npxs|=C1;
- CLOCK_CYCLES(100);
+ CLOCK_CYCLES(x87_timings.fprem1);
return 0;
}
@@ -605,7 +635,7 @@ static int opFSQRT(uint32_t fetchdat)
if (fplog) pclog("FSQRT\n");
ST(0) = sqrt(ST(0));
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
- CLOCK_CYCLES(83);
+ CLOCK_CYCLES(x87_timings.fsqrt);
return 0;
}
@@ -620,7 +650,7 @@ static int opFSINCOS(uint32_t fetchdat)
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
x87_push(cos(td));
cpu_state.npxs &= ~C2;
- CLOCK_CYCLES(330);
+ CLOCK_CYCLES(x87_timings.fsincos);
return 0;
}
@@ -632,7 +662,7 @@ static int opFRNDINT(uint32_t fetchdat)
ST(0) = (double)x87_fround(ST(0));
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
if (fplog) pclog("%g\n", ST(0));
- CLOCK_CYCLES(21);
+ CLOCK_CYCLES(x87_timings.frndint);
return 0;
}
@@ -643,9 +673,10 @@ static int opFSCALE(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FSCALE\n");
temp64 = (int64_t)ST(1);
- ST(0) = ST(0) * pow(2.0, (double)temp64);
+ if (ST(0) != 0.0)
+ ST(0) = ST(0) * pow(2.0, (double)temp64);
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
- CLOCK_CYCLES(30);
+ CLOCK_CYCLES(x87_timings.fscale);
return 0;
}
@@ -657,7 +688,7 @@ static int opFSIN(uint32_t fetchdat)
ST(0) = sin(ST(0));
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
cpu_state.npxs &= ~C2;
- CLOCK_CYCLES(300);
+ CLOCK_CYCLES(x87_timings.fsin_cos);
return 0;
}
@@ -669,7 +700,7 @@ static int opFCOS(uint32_t fetchdat)
ST(0) = cos(ST(0));
cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
cpu_state.npxs &= ~C2;
- CLOCK_CYCLES(300);
+ CLOCK_CYCLES(x87_timings.fsin_cos);
return 0;
}
@@ -697,7 +728,7 @@ static int FLDENV()
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
break;
}
- CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
+ CLOCK_CYCLES(x87_timings.fldenv);
return cpu_state.abrt;
}
@@ -729,7 +760,7 @@ static int opFLDCW_a16(uint32_t fetchdat)
if (cpu_state.abrt) return 1;
cpu_state.npxc = tempw;
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fldcw);
return 0;
}
static int opFLDCW_a32(uint32_t fetchdat)
@@ -743,7 +774,7 @@ static int opFLDCW_a32(uint32_t fetchdat)
if (cpu_state.abrt) return 1;
cpu_state.npxc = tempw;
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fldcw);
return 0;
}
@@ -751,6 +782,8 @@ static int FSTENV()
{
FP_ENTER();
if (fplog) pclog("FSTENV %08X:%08X\n", easeg, cpu_state.eaaddr);
+ cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | ((cpu_state.TOP & 7) << 11);
+
switch ((cr0 & 1) | (cpu_state.op32 & 0x100))
{
case 0x000: /*16-bit real mode*/
@@ -787,7 +820,7 @@ static int FSTENV()
writememl(easeg,cpu_state.eaaddr+24,x87_op_seg);
break;
}
- CLOCK_CYCLES((cr0 & 1) ? 56 : 67);
+ CLOCK_CYCLES(x87_timings.fstenv);
return cpu_state.abrt;
}
@@ -815,7 +848,7 @@ static int opFSTCW_a16(uint32_t fetchdat)
SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTCW %08X:%08X\n", easeg, cpu_state.eaaddr);
seteaw(cpu_state.npxc);
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fstcw_sw);
return cpu_state.abrt;
}
static int opFSTCW_a32(uint32_t fetchdat)
@@ -825,7 +858,7 @@ static int opFSTCW_a32(uint32_t fetchdat)
SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTCW %08X:%08X\n", easeg, cpu_state.eaaddr);
seteaw(cpu_state.npxc);
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fstcw_sw);
return cpu_state.abrt;
}
diff --git a/src/x87_timings.c b/src/x87_timings.c
new file mode 100644
index 0000000..757f05c
--- /dev/null
+++ b/src/x87_timings.c
@@ -0,0 +1,309 @@
+#include "ibm.h"
+#include "x87_timings.h"
+
+x87_timings_t x87_timings;
+
+const x87_timings_t x87_timings_8087 =
+{
+ .f2xm1 = (310 + 630) / 2,
+ .fabs = (10 + 17) / 2,
+ .fadd = (70 + 100) / 2,
+ .fadd_32 = (90 + 120) / 2,
+ .fadd_64 = (95 + 125) / 2,
+ .fbld = (290 + 310) / 2,
+ .fbstp = (520 + 540) / 2,
+ .fchs = (10 + 17) / 2,
+ .fclex = (2 + 8) / 2,
+ .fcom = (40 + 50) / 2,
+ .fcom_32 = (60 + 70) / 2,
+ .fcom_64 = (65 + 75) / 2,
+ .fcos = 0, /*387+*/
+ .fincdecstp = (6 + 12) / 2,
+ .fdisi_eni = (6 + 12) / 2,
+ .fdiv = (193 + 203) / 2,
+ .fdiv_32 = (215 + 225) / 2,
+ .fdiv_64 = (220 + 230) / 2,
+ .ffree = (9 + 16) / 2,
+ .fadd_i16 = (102 + 137) / 2,
+ .fadd_i32 = (108 + 143) / 2,
+ .fcom_i16 = (72 + 86) / 2,
+ .fcom_i32 = (78 + 91) / 2,
+ .fdiv_i16 = (224 + 238) / 2,
+ .fdiv_i32 = (230 + 243) / 2,
+ .fild_16 = (46 + 54) / 2,
+ .fild_32 = (50 + 60) / 2,
+ .fild_64 = (60 + 68) / 2,
+ .fmul_i16 = (124 + 138) / 2,
+ .fmul_i32 = (130 + 144) / 2,
+ .finit = (2 + 8) / 2,
+ .fist_16 = (80 + 90) / 2,
+ .fist_32 = (82 + 92) / 2,
+ .fist_64 = (94 + 105) / 2,
+ .fld = (17 + 22) / 2,
+ .fld_32 = (38 + 56) / 2,
+ .fld_64 = (40 + 60) / 2,
+ .fld_80 = (53 + 65) / 2,
+ .fld_z1 = (11 + 21) / 2,
+ .fld_const = (15 + 24) / 2,
+ .fldcw = (7 + 14) / 2,
+ .fldenv = (35 + 45) / 2,
+ .fmul = (90 + 145) / 2,
+ .fmul_32 = (110 + 125) / 2,
+ .fmul_64 = (154 + 168) / 2,
+ .fnop = (10 + 16) / 2,
+ .fpatan = (250 + 800) / 2,
+ .fprem = (15 + 190) / 2,
+ .fprem1 = 0, /*387+*/
+ .fptan = (30 + 540) / 2,
+ .frndint = (16 + 50) / 2,
+ .frstor = (197 + 207) / 2,
+ .fsave = (197 + 207) / 2,
+ .fscale = (32 + 38) / 2,
+ .fsetpm = 0, /*287+*/
+ .fsin_cos = 0, /*387+*/
+ .fsincos = 0, /*387+*/
+ .fsqrt = (180 + 186) / 2,
+ .fst = (15 + 22) / 2,
+ .fst_32 = (84 + 90) / 2,
+ .fst_64 = (96 + 104) / 2,
+ .fst_80 = (52 + 58) / 2,
+ .fstcw_sw = (12 + 18) / 2,
+ .fstenv = (40 + 50) / 2,
+ .ftst = (38 + 48) / 2,
+ .fucom = 0, /*387+*/
+ .fwait = 4,
+ .fxam = (12 + 23) / 2,
+ .fxch = (10 + 15) / 2,
+ .fxtract = (27 + 55) / 2,
+ .fyl2x = (900 + 1100) / 2,
+ .fyl2xp1 = (700 + 1000) / 2
+};
+
+/*Mostly the same as 8087*/
+const x87_timings_t x87_timings_287 =
+{
+ .f2xm1 = (310 + 630) / 2,
+ .fabs = (10 + 17) / 2,
+ .fadd = (70 + 100) / 2,
+ .fadd_32 = (90 + 120) / 2,
+ .fadd_64 = (95 + 125) / 2,
+ .fbld = (290 + 310) / 2,
+ .fbstp = (520 + 540) / 2,
+ .fchs = (10 + 17) / 2,
+ .fclex = (2 + 8) / 2,
+ .fcom = (40 + 50) / 2,
+ .fcom_32 = (60 + 70) / 2,
+ .fcom_64 = (65 + 75) / 2,
+ .fcos = 0, /*387+*/
+ .fincdecstp = (6 + 12) / 2,
+ .fdisi_eni = 2,
+ .fdiv = (193 + 203) / 2,
+ .fdiv_32 = (215 + 225) / 2,
+ .fdiv_64 = (220 + 230) / 2,
+ .ffree = (9 + 16) / 2,
+ .fadd_i16 = (102 + 137) / 2,
+ .fadd_i32 = (108 + 143) / 2,
+ .fcom_i16 = (72 + 86) / 2,
+ .fcom_i32 = (78 + 91) / 2,
+ .fdiv_i16 = (224 + 238) / 2,
+ .fdiv_i32 = (230 + 243) / 2,
+ .fild_16 = (46 + 54) / 2,
+ .fild_32 = (50 + 60) / 2,
+ .fild_64 = (60 + 68) / 2,
+ .fmul_i16 = (124 + 138) / 2,
+ .fmul_i32 = (130 + 144) / 2,
+ .finit = (2 + 8) / 2,
+ .fist_16 = (80 + 90) / 2,
+ .fist_32 = (82 + 92) / 2,
+ .fist_64 = (94 + 105) / 2,
+ .fld = (17 + 22) / 2,
+ .fld_32 = (38 + 56) / 2,
+ .fld_64 = (40 + 60) / 2,
+ .fld_80 = (53 + 65) / 2,
+ .fld_z1 = (11 + 21) / 2,
+ .fld_const = (15 + 24) / 2,
+ .fldcw = (7 + 14) / 2,
+ .fldenv = (35 + 45) / 2,
+ .fmul = (90 + 145) / 2,
+ .fmul_32 = (110 + 125) / 2,
+ .fmul_64 = (154 + 168) / 2,
+ .fnop = (10 + 16) / 2,
+ .fpatan = (250 + 800) / 2,
+ .fprem = (15 + 190) / 2,
+ .fprem1 = 0, /*387+*/
+ .fptan = (30 + 540) / 2,
+ .frndint = (16 + 50) / 2,
+ .frstor = (197 + 207) / 2,
+ .fsave = (197 + 207) / 2,
+ .fscale = (32 + 38) / 2,
+ .fsetpm = (2 + 8) / 2, /*287+*/
+ .fsin_cos = 0, /*387+*/
+ .fsincos = 0, /*387+*/
+ .fsqrt = (180 + 186) / 2,
+ .fst = (15 + 22) / 2,
+ .fst_32 = (84 + 90) / 2,
+ .fst_64 = (96 + 104) / 2,
+ .fst_80 = (52 + 58) / 2,
+ .fstcw_sw = (12 + 18) / 2,
+ .fstenv = (40 + 50) / 2,
+ .ftst = (38 + 48) / 2,
+ .fucom = 0, /*387+*/
+ .fwait = 3,
+ .fxam = (12 + 23) / 2,
+ .fxch = (10 + 15) / 2,
+ .fxtract = (27 + 55) / 2,
+ .fyl2x = (900 + 1100) / 2,
+ .fyl2xp1 = (700 + 1000) / 2
+};
+
+const x87_timings_t x87_timings_387 =
+{
+ .f2xm1 = (211 + 476) / 2,
+ .fabs = 22,
+ .fadd = (23 + 34) / 2,
+ .fadd_32 = (24 + 32) / 2,
+ .fadd_64 = (29 + 37) / 2,
+ .fbld = (266 + 275) / 2,
+ .fbstp = (512 + 534) / 2,
+ .fchs = (24 + 25) / 2,
+ .fclex = 11,
+ .fcom = 24,
+ .fcom_32 = 26,
+ .fcom_64 = 31,
+ .fcos = (122 + 772) / 2,
+ .fincdecstp = 22,
+ .fdisi_eni = 2,
+ .fdiv = (88 + 91) / 2,
+ .fdiv_32 = 89,
+ .fdiv_64 = 94,
+ .ffree = 18,
+ .fadd_i16 = (71 + 85) / 2,
+ .fadd_i32 = (57 + 72) / 2,
+ .fcom_i16 = (71 + 75) / 2,
+ .fcom_i32 = (56 + 63) / 2,
+ .fdiv_i16 = (136 + 140) / 2,
+ .fdiv_i32 = (120 + 127) / 2,
+ .fild_16 = (61 + 65) / 2,
+ .fild_32 = (45 + 52) / 2,
+ .fild_64 = (56 + 67) / 2,
+ .fmul_i16 = (76 + 87) / 2,
+ .fmul_i32 = (61 + 82) / 2,
+ .finit = 33,
+ .fist_16 = (82 + 95) / 2,
+ .fist_32 = (79 + 93) / 2,
+ .fist_64 = (80 + 97) / 2,
+ .fld = 14,
+ .fld_32 = 20,
+ .fld_64 = 25,
+ .fld_80 = 44,
+ .fld_z1 = (20 + 24) / 2,
+ .fld_const = 40,
+ .fldcw = 19,
+ .fldenv = 71,
+ .fmul = (29 + 57) / 2,
+ .fmul_32 = (27 + 35) / 2,
+ .fmul_64 = (32 + 57) / 2,
+ .fnop = 12,
+ .fpatan = (314 + 487) / 2,
+ .fprem = (74 + 155) / 2,
+ .fprem1 = (95 + 185) / 2,
+ .fptan = (191 + 497) / 2,
+ .frndint = (66 + 80) / 2,
+ .frstor = 308,
+ .fsave = 375,
+ .fscale = (67 + 86) / 2,
+ .fsetpm = 12,
+ .fsin_cos = (122 + 771) / 2,
+ .fsincos = (194 + 809) / 2,
+ .fsqrt = (122 + 129) / 2,
+ .fst = 11,
+ .fst_32 = 44,
+ .fst_64 = 45,
+ .fst_80 = 53,
+ .fstcw_sw = 15,
+ .fstenv = 103,
+ .ftst = 28,
+ .fucom = 24,
+ .fwait = 6,
+ .fxam = (30 + 38) / 2,
+ .fxch = 18,
+ .fxtract = (70 + 76) / 2,
+ .fyl2x = (120 + 538) / 2,
+ .fyl2xp1 = (257 + 547) / 2
+};
+
+const x87_timings_t x87_timings_486 =
+{
+ .f2xm1 = (140 + 270) / 2,
+ .fabs = 3,
+ .fadd = (8 + 20) / 2,
+ .fadd_32 = (8 + 20) / 2,
+ .fadd_64 = (8 + 20) / 2,
+ .fbld = (70 + 103) / 2,
+ .fbstp = (172 + 176) / 2,
+ .fchs = 6,
+ .fclex = 7,
+ .fcom = 4,
+ .fcom_32 = 4,
+ .fcom_64 = 4,
+ .fcos = (257 + 354) / 2,
+ .fincdecstp = 3,
+ .fdisi_eni = 3,
+ .fdiv = 73,
+ .fdiv_32 = 73,
+ .fdiv_64 = 73,
+ .ffree = 3,
+ .fadd_i16 = (20 + 35) / 2,
+ .fadd_i32 = (19 + 32) / 2,
+ .fcom_i16 = (16 + 20) / 2,
+ .fcom_i32 = (15 + 17) / 2,
+ .fdiv_i16 = (85 + 89) / 2,
+ .fdiv_i32 = (84 + 86) / 2,
+ .fild_16 = (13 + 16) / 2,
+ .fild_32 = (9 + 12) / 2,
+ .fild_64 = (10 + 18) / 2,
+ .fmul_i16 = (23 + 27) / 2,
+ .fmul_i32 = (22 + 24) / 2,
+ .finit = 17,
+ .fist_16 = (29 + 34) / 2,
+ .fist_32 = (28 + 34) / 2,
+ .fist_64 = (29 + 34) / 2,
+ .fld = 4,
+ .fld_32 = 3,
+ .fld_64 = 3,
+ .fld_80 = 6,
+ .fld_z1 = 4,
+ .fld_const = 8,
+ .fldcw = 4,
+ .fldenv = 34,
+ .fmul = 16,
+ .fmul_32 = 11,
+ .fmul_64 = 14,
+ .fnop = 3,
+ .fpatan = (218 + 303) / 2,
+ .fprem = (70 + 138) / 2,
+ .fprem1 = (72 + 167) / 2,
+ .fptan = (200 + 273) / 2,
+ .frndint = (21 + 30) / 2,
+ .frstor = 120,
+ .fsave = 143,
+ .fscale = (30 + 32) / 2,
+ .fsetpm = 3,
+ .fsin_cos = (257 + 354) / 2,
+ .fsincos = (292 + 365) / 2,
+ .fsqrt = (83 + 87) / 2,
+ .fst = 3,
+ .fst_32 = 7,
+ .fst_64 = 8,
+ .fst_80 = 6,
+ .fstcw_sw = 3,
+ .fstenv = 56,
+ .ftst = 4,
+ .fucom = 4,
+ .fwait = (1 + 3) / 2,
+ .fxam = 8,
+ .fxch = 4,
+ .fxtract = (16 + 20) / 2,
+ .fyl2x = (196 + 329) / 2,
+ .fyl2xp1 = (171 + 326) / 2
+};
diff --git a/src/x87_timings.h b/src/x87_timings.h
new file mode 100644
index 0000000..14ab7dd
--- /dev/null
+++ b/src/x87_timings.h
@@ -0,0 +1,56 @@
+typedef struct
+{
+ int f2xm1;
+ int fabs;
+ int fadd, fadd_32, fadd_64;
+ int fbld;
+ int fbstp;
+ int fchs;
+ int fclex;
+ int fcom, fcom_32, fcom_64;
+ int fcos;
+ int fincdecstp;
+ int fdisi_eni;
+ int fdiv, fdiv_32, fdiv_64;
+ int ffree;
+ int fadd_i16, fadd_i32;
+ int fcom_i16, fcom_i32;
+ int fdiv_i16, fdiv_i32;
+ int fild_16, fild_32, fild_64;
+ int fmul_i16, fmul_i32;
+ int finit;
+ int fist_16, fist_32, fist_64;
+ int fld, fld_32, fld_64, fld_80;
+ int fld_z1, fld_const;
+ int fldcw;
+ int fldenv;
+ int fmul, fmul_32, fmul_64;
+ int fnop;
+ int fpatan;
+ int fprem, fprem1;
+ int fptan;
+ int frndint;
+ int frstor;
+ int fsave;
+ int fscale;
+ int fsetpm;
+ int fsin_cos, fsincos;
+ int fsqrt;
+ int fst, fst_32, fst_64, fst_80;
+ int fstcw_sw;
+ int fstenv;
+ int ftst;
+ int fucom;
+ int fwait;
+ int fxam;
+ int fxch;
+ int fxtract;
+ int fyl2x, fyl2xp1;
+} x87_timings_t;
+
+extern const x87_timings_t x87_timings_8087;
+extern const x87_timings_t x87_timings_287;
+extern const x87_timings_t x87_timings_387;
+extern const x87_timings_t x87_timings_486;
+
+extern x87_timings_t x87_timings;
diff --git a/src/xi8088.c b/src/xi8088.c
index 6ea95e6..1c5a135 100644
--- a/src/xi8088.c
+++ b/src/xi8088.c
@@ -28,12 +28,12 @@ void xi8088_turbo_set(uint8_t value)
xi8088.turbo = value;
if (!value)
{
- pclog("Xi8088 turbo off\n");
+// pclog("Xi8088 turbo off\n");
cpu_set_turbo(0);
}
else
{
- pclog("Xi8088 turbo on\n");
+// pclog("Xi8088 turbo on\n");
cpu_set_turbo(1);
}
}
@@ -45,7 +45,6 @@ int xi8088_bios_128kb()
static void *xi8088_init()
{
- /* even though the bios by default turns the turbo off when controlling by hotkeys, pcem always starts at full speed */
xi8088.turbo = 1;
xi8088.turbo_setting = device_get_config_int("turbo_setting");
xi8088.bios_128kb = device_get_config_int("bios_128kb");
@@ -66,7 +65,7 @@ static device_config_t xi8088_config[] =
.value = 0
},
{
- .description = "Hotkeys (starts off)",
+ .description = "BIOS setting + Hotkeys (off during POST)",
.value = 1
}
},
@@ -79,16 +78,52 @@ static device_config_t xi8088_config[] =
.selection =
{
{
- .description = "64KB",
+ .description = "64KB starting from 0xF0000",
.value = 0
},
{
- .description = "128KB",
+ .description = "128KB starting from 0xE0000 (address MSB inverted, last 64KB first)",
.value = 1
}
},
.default_int = 1
},
+ {
+ .name = "umb_c0000h_c7fff",
+ .description = "Map 0xc0000-0xc7fff as UMB",
+ .type = CONFIG_BINARY,
+ .default_int = 0
+ },
+ {
+ .name = "umb_c8000h_cffff",
+ .description = "Map 0xc8000-0xcffff as UMB",
+ .type = CONFIG_BINARY,
+ .default_int = 0
+ },
+ {
+ .name = "umb_d0000h_d7fff",
+ .description = "Map 0xd0000-0xd7fff as UMB",
+ .type = CONFIG_BINARY,
+ .default_int = 0
+ },
+ {
+ .name = "umb_d8000h_dffff",
+ .description = "Map 0xd8000-0xdffff as UMB",
+ .type = CONFIG_BINARY,
+ .default_int = 0
+ },
+ {
+ .name = "umb_e0000h_e7fff",
+ .description = "Map 0xe0000-0xe7fff as UMB",
+ .type = CONFIG_BINARY,
+ .default_int = 0
+ },
+ {
+ .name = "umb_e8000h_effff",
+ .description = "Map 0xe8000-0xeffff as UMB",
+ .type = CONFIG_BINARY,
+ .default_int = 0
+ },
{
.type = -1
}
diff --git a/src/zenith.c b/src/zenith.c
new file mode 100644
index 0000000..f7f361b
--- /dev/null
+++ b/src/zenith.c
@@ -0,0 +1,50 @@
+#include
+#include "ibm.h"
+#include "device.h"
+#include "mem.h"
+#include "zenith.h"
+
+static uint8_t *zenith_scratchpad_ram;
+static mem_mapping_t zenith_scratchpad_mapping;
+
+static uint8_t zenith_scratchpad_read(uint32_t addr, void *p)
+{
+ return zenith_scratchpad_ram[addr & 0x3fff];
+}
+static void zenith_scratchpad_write(uint32_t addr, uint8_t val, void *p)
+{
+ zenith_scratchpad_ram[addr & 0x3fff] = val;
+}
+
+static void *zenith_scratchpad_init()
+{
+ zenith_scratchpad_ram = malloc(0x4000);
+
+ mem_mapping_disable(&bios_mapping[4]);
+ mem_mapping_disable(&bios_mapping[5]);
+
+ mem_mapping_add(&zenith_scratchpad_mapping, 0xf0000, 0x4000,
+ zenith_scratchpad_read, NULL, NULL,
+ zenith_scratchpad_write, NULL, NULL,
+ zenith_scratchpad_ram, MEM_MAPPING_EXTERNAL, NULL);
+
+ return zenith_scratchpad_ram;
+}
+
+static void zenith_scratchpad_close(void *p)
+{
+ free(p);
+}
+
+device_t zenith_scratchpad_device =
+{
+ "Zenith scratchpad RAM",
+ 0,
+ zenith_scratchpad_init,
+ zenith_scratchpad_close,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
diff --git a/src/zenith.h b/src/zenith.h
new file mode 100644
index 0000000..0e58f45
--- /dev/null
+++ b/src/zenith.h
@@ -0,0 +1 @@
+device_t zenith_scratchpad_device;
diff --git a/tested.html b/tested.html
new file mode 100644
index 0000000..0480f1d
--- /dev/null
+++ b/tested.html
@@ -0,0 +1,493 @@
+
+
+
+
+
+
+ tested
+
+
+
+
+Software tested (v17):
+DOS
+
+PC-DOS 1.0
+MS-DOS 2.11
+MS-DOS 3.30
+MS-DOS 4.01
+MS-DOS 5.0
+MS-DOS 6.0
+MS-DOS 6.22
+
+Windows
+
+Windows 1.04
+Windows/286 2.11
+Windows/386 2.11
+Windows 3.0
+Windows 3.1
+Windows for Workgroups 3.11
+Windows 95
+Windows 95 OSR2
+Windows 98SE
+Windows ME
+
+Windows NT
+
+Windows NT 3.1
+Windows NT 3.51
+Windows NT 4 Workstation (SP6a)
+Windows 2000
+Windows XP
+
+OS/2
+
+OS/2 v1.0
+OS/2 v1.1
+OS/2 v1.2
+OS/2 v1.3
+OS/2 v2.1
+OS/2 Warp 3
+OS/2 Warp 4
+
+Linux
+
+Corel Linux 1.2
+Mandriva LE 2005
+Red Hat Linux 7.1 (Seawolf)
+
+BeOS
+
+BeOS 5.0 Professional Edition
+
+Applications
+
+3DMark 2000
+3DMark 2001SE
+After Dark 3.06
+Cinemania 1994
+Creative Writer
+Cubasis
+Encarta 1994
+Fasttracker v2.08
+PageMaker 5.0
+PC Paintbrush 1.05
+Photoshop 3.0
+Smartsuite 97
+Visual Basic 3.0
+Visual C++ 6.0
+Word for Windows 2.0
+Winzip 6.2
+
+Games
+
+1602 AD (demo)
+3D Ultra Pinball Thrillride
+A-10 Tank Killer
+Actua Soccer
+Adventure Pinball Forgotten Island (demo)
+Aladdin
+Alien vs Predator
+Alien vs Predator 2 (demo)
+All New World of Lemmings
+Alone in the Dark
+Alone in the Dark : The New Nightmare (demo)
+Anachronox
+Arkanoid
+Armoured Fist 3 (demo)
+Asteroids (1998)
+B-17 Flying Fortress
+Battle Chess
+Battlezone
+Battlezone II
+Bejeweled
+Beyond Castle Wolfenstein
+Big Red Racing
+Bio Menace
+Black & White
+Brix
+Bugs Bunny Lost In Time (demo)
+Cannon Fodder 2
+Carnivores 2
+Civilization
+Civilization for Windows
+Claw
+Clive Barker's Undying (demo)
+Clockwiser
+Command & Conquer : Red Alert
+Command & Conquer : Red Alert 2
+Command & Conquer : Tiberian Sun (demo)
+Command & Conquer Renegade
+Conquest
+Corridor 7
+Counter-Strike 2D
+Crimson Skies (demo)
+Croc
+Curse of Monkey Island
+Cutthroats (demo)
+Daikatana
+Dawn Patrol
+Day of the Tentacle
+Dance Dance Revolution
+Dead Reckoning (demo)
+Death Drome
+Desert Strike
+Digger
+Dirt Track Racing (demo)
+Disciples (demo)
+Discworld II
+Doom (v1.2)
+Doom II (v1.666)
+Double Dragon
+Drakan (demo)
+Duke Nukem 3D (v1.3D)
+Dune
+DX-Ball 2
+Echelon
+Ecstatica
+Epic Pinball
+Every Extend
+Evolva (demo)
+Expendable
+Eye of the Beholder
+Fallout Tactics (demo)
+Final Fantasy VIII (demo)
+Flashback
+Flight Simulator 5
+Frogger
+Frontier : First Encounters
+Gabriel Knight 3 (demo)
+Giants : Citizen Kabuto
+GLQuake
+Grand Theft Auto 2
+Half-Life
+Halloween Harry
+Heartlight
+Hellbender
+Hexen
+High Heat Baseball 2002 (demo)
+Hitch Hiker's Guide to the Galaxy
+Hocus Pocus
+Homeworld Cataclysm (demo)
+Incoming
+James Pond 2 : Robocod
+Jazz Jackrabbit
+Jazz Jackrabbit 2
+Jill of the Jungle
+King's Quest
+King's Quest II
+King's Quest III
+Lemmings
+Lemmings 2 : The Tribes
+Lode Runner : The Legend Continues
+Lotus III
+Madden 2002 (demo)
+Majesty (demo)
+Maniac Mansion (enhanced)
+Max Payne
+MDK (Direct3D, USA release)
+MechCommander 2
+Mechwarrior 2
+Mechwarrior 3
+Megaman Legends
+Metal Gear Solid
+Microsoft Arcade
+Microsoft Golf 99 (demo)
+Midtown Madness 2 (demo)
+Monaco Grand Prix (demo)
+Monkey Island 2
+Monster Bash
+Monster Truck Madness
+Mortal Kombat
+Mortal Kombat 2
+Mortal Kombat 3
+Motorcross Madness (demo)
+Mystic Towers
+Nascar Heat
+Need for Speed II SE
+Need for Speed III
+Need for Speed : High Stakes
+NHL 2001 (demo)
+No One Lives Forever
+Oddworld : Abe's Exoddus
+One Must Fall 2097
+Oni
+Outlaws
+Pacific Strike
+Pacman Adventures in Time (demo)
+Pharoah (demo)
+Pinball Fantasies
+Pinball Illusions
+Police Quest
+Police Quest 2
+Porrasturvat
+Power Drive
+Prince of Persia
+Prince of Persia 3D (demo)
+Pro Pinball : The Web
+Psycho Pinball
+Quake
+Quake II
+Quake III Arena
+Rayman 2 (demo)
+Red Faction
+Redline Racer
+Rise of the Triad (v1.2)
+Screamer
+Sega Rally 2 (demo)
+Sensible World of Soccer
+Settlers 3 (demo)
+Severance : Blade of Darkness (demo)
+Shadow Company (demo)
+Shadow Warrior
+Shadowman (demo)
+Sid Meier's Alien Crossfire (demo)
+SimCity 2000
+SimCity Classic
+SimTower
+Sink or Swim
+Soldat (1.0.5)
+Sonic CD
+Space Simulator
+Space Strike
+Spider-Man (demo)
+Springy Madness
+Star Trek Hidden Evil (demo)
+Star Trek Voyager Elite Force
+Star Wars Jedi Academy
+Starfleet Command 2 (demo)
+Stargunner
+Starlancer (demo)
+Steel Beasts (demo)
+Stunt Island
+SWAT 3 Elite Edition (demo)
+Syndicate
+System Shock
+Tanktics (demo)
+Terminal Velocity
+The Dig
+The Humans
+The Labyrinth (RealArcade version)
+The Lost Vikings
+The Ultimate Doom (v1.9)
+Theme Hospital
+Theme Park
+Tomb Raider
+Tomb Raider II
+Tomb Raider The Last Revelation (demo)
+Tony Hawk's Pro Skater 2
+Transport Tycoon
+Transport Tycoon Deluxe
+Tropico (demo)
+Turrican 2
+UFO : Enemy Unknown
+Ultimate Ride (demo)
+Unreal
+Unreal Tournament
+Unreal Tournament 2004 (Direct3D)
+Wacky Wheels
+Warlords Battlecry (demo)
+Wheel of Time (demo)
+Wing Commander
+Wing Commander : Privateer
+Wizkid
+Wolfenstein 3D
+World War III : Black Gold (demo)
+Worms
+Worms Armageddon
+X-Com : Terror From The Deep
+Xargon
+Z : Steel Soldiers (demo)
+Zak McKracken
+Zone 66
+
+Demos
+
+Cascada - Cronologia
+Coma - Paimen
+Complex - Cyboman 2
+Complex - Dope
+EMF - Verses
+Exceed - Heaven 7
+Future Crew - Second Reality
+Gazebo - Cyboman
+Halcyon - Lifeforms
+Iguana - Heartquake
+Impact Studios - Legend
+Impact Studios - Project Angel
+KFMF - Dance, Move, Shake
+KFMF - Trip
+Logic Design - Fashion
+Majic 12 - Show
+Majic 12 - Wish
+Megabusters - Hellraiser
+Orange - x14
+Renaissance - Amnesia
+Skull - Putre Faction
+Tran - Ambience (flickery)
+Tran - Luminati (flickery)
+Tran - Timeless
+Triton - Crystal Dream
+Triton - Crystal Dream 2
+Ultraforce - Coldcut
+Ultraforce - Vector Demo
+Valhalla - Solstice
+Witan - Witan House
+
+Emulators
+
+Beebem v1.02
+BeebInC v0.99f
+CPE v5.2i
+DOSBox 0.74-3
+Fellow 0.33
+KGen98 v0.4b
+PaCifiST v0.48
+SNES9x v0.96
+UltraHLE v1.0.0
+vMac v0.1.9.1
+ZSNES v0.800c
+
+
+